{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>.container { width:100% !important; }</style>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from IPython.core.display import display, HTML\n",
    "display(HTML(\"<style>.container { width:100% !important; }</style>\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Device info: GeForce GTX 1050 Ti\n"
     ]
    }
   ],
   "source": [
    "import scipy.io\n",
    "from mpl_toolkits.axes_grid1 import make_axes_locatable\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.optim as optim\n",
    "from torch.optim.lr_scheduler import StepLR\n",
    "\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from mpl_toolkits.mplot3d import Axes3D\n",
    "from matplotlib import cm\n",
    "import os\n",
    "from pyDOE import lhs\n",
    "import shutil\n",
    "\n",
    "import argparse\n",
    "\n",
    "# 设置随机数种子\n",
    "torch.manual_seed(123)\n",
    "np.random.seed(123)\n",
    "\n",
    "print(f'Device info: {torch.cuda.get_device_name()}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 实验报告\n",
    "\n",
    "姓名：江金阳\n",
    "\n",
    "学号：2017301000090\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 0 概要\n",
    "\n",
    "报告中对原论文各个算例的结果分别进行了复现，其中Burgers方程和Shrödinger方程的实现思想与原文相同，都采用了连续时间的模型，选取MSEloss，将PDE各式嵌入DNN的loss函数中得到PINN框架，最终的结果与作者提供的数值结果几乎吻合，效果理想。\n",
    "\n",
    "而在Allen-Cahn方程的实现中，因为两点原因我最终**沿用了Shrödinger方程的实现思想**而没有使用作者的，其一，作者的loss计算是在已知数值解的前提下进行的，作者的工作可能只是建立了一个较强的拟合网络；其二，作者用Runge-Kutta方法将PDE转化为离散形式地嵌入loss函数中这一做法需要在多层新增较多个神经元，我所使用设备的显存在合理的超参数下始终无法支持运行下来。在我自己的实现方式下，所取得的结果与作者的结果有少许差别，主要是PDE解的正中位置的细节表现得不够理想，根据下面对照实验中的结论，适当增加网络的隐藏元个数和取样密度，提高网络对细节特征的学习应该可以取得更理想的结果。\n",
    "\n",
    "**根据Burgers方程和Shrödinger方程的对照实验结果，我得出了如下的定性结论：**\n",
    "\n",
    "1.相同的超参数下，PINN和ResPINN相比，ResPINN的学习效率更高，loss下降得更快；此外在调参过程中发现，ResPINN更为稳定高效，可以允许使用更深的隐藏层数而不发生梯度弥散或梯度爆炸，但对于PINN来说，粗暴地叠加网络深度后会有网络退化的问题，在超过某个层数后训练误差不降反升。\n",
    "\n",
    "2.固定隐藏元个数，隐藏层/残差块数越多，网络越深，网络的泛化能力越好，可以在训练数据中学到更抽象的特征。\n",
    "\n",
    "3.固定隐藏层数/残差块数，隐藏元个数越多，网络越宽，网络对训练数据的细节特征学习得越好，是一个好的“拟合”工具，但是泛化能力不足，更换数据后所得结果不尽理想。\n",
    "\n",
    "4.过高的隐藏元个数、隐藏层数/残差块数和过大的训练轮数都可以导致过拟合，但相比较而言宽网络比深网络更容易过拟合。\n",
    "\n",
    "**具体的对照实验结果见各章末尾。**\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1、基础网络结构"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "网络结构分为普通的和带残差的全连接前馈神经网络(Fully-Connected Feedforward Network)，选择其中一种来实现。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### DNN"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def activation(name):\n",
    "    '''\n",
    "    Activation function switcher\n",
    "    '''\n",
    "    if name.upper() == 'TANH':\n",
    "        return nn.Tanh()\n",
    "    elif name.upper() == 'RELU':\n",
    "        return nn.ReLU(inplace=True)\n",
    "    elif name in ['leaky_relu', 'LeakyReLU']:\n",
    "        return nn.LeakyReLU(inplace=True)\n",
    "    elif name.upper() == 'SIGMOID':\n",
    "        return nn.Sigmoid()\n",
    "    elif name.upper() == 'SOFTPLUS':\n",
    "        return nn.Softplus()\n",
    "    else: \n",
    "        raise ValueError(f'Unknown activation function: {name}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "class DNN(nn.Module):\n",
    "    '''\n",
    "    Deep Neural Network\n",
    "    '''\n",
    "    def __init__(self, dim_in, dim_out, dim_hidden, hidden_layers, act_name = 'tanh', init_name = 'kaiming_normal'):\n",
    "        super().__init__()\n",
    "        model = nn.Sequential()\n",
    "        \n",
    "        model.add_module('fc0',nn.Linear(dim_in, dim_hidden, bias = True))\n",
    "        model.add_module('act0', activation(act_name))\n",
    "\n",
    "        for i in range(1, hidden_layers):\n",
    "            model.add_module(f'fc{i}', nn.Linear(dim_hidden, dim_hidden, bias=True))\n",
    "            model.add_module(f'act{i}', activation(act_name))\n",
    "             \n",
    "        model.add_module(f'fc{hidden_layers}', nn.Linear(dim_hidden, dim_out, bias=True))\n",
    "        \n",
    "        self.model = model\n",
    "             \n",
    "        if init_name is not None:\n",
    "            self.init_weight(init_name)\n",
    "    \n",
    "    def init_weight(self, init_name):\n",
    "        if init_name == 'xavier_normal':\n",
    "            nn_init = nn.init.xavier_normal_\n",
    "        elif init_name == 'xavier_uniform':\n",
    "            nn_init = nn.init.xavier_uniform_\n",
    "        elif init_name == 'kaiming_normal':\n",
    "            nn_init = nn.init.kaiming_normal_\n",
    "        elif init_name == 'kaiming_uniform':\n",
    "            nn_init =  nn.init.kaiming_uniform_\n",
    "        else:\n",
    "            raise ValueError(f'unknown initialization function: {init_name}')\n",
    "            \n",
    "        for param in self.parameters():\n",
    "            if len(param.shape) > 1:\n",
    "                nn_init(param)\n",
    "\n",
    "    def forward(self, x):\n",
    "        return self.model(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### ResDNN"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ResBlock(nn.Module):\n",
    "    '''\n",
    "    Residual Block \n",
    "    '''\n",
    "    def __init__(self, dim_in, dim_out, dim_hidden, act_name='tanh'):\n",
    "        super().__init__()\n",
    "\n",
    "        assert(dim_in == dim_out)\n",
    "        \n",
    "        block = nn.Sequential()\n",
    "        block.add_module('act', activation(act_name))\n",
    "        block.add_module('fc0', nn.Linear(dim_in, dim_hidden, bias=True))\n",
    "        block.add_module('fc1', nn.Linear(dim_hidden, dim_out, bias=True))\n",
    "        self.block = block\n",
    "\n",
    "    def forward(self, x):\n",
    "        res = x\n",
    "        out = self.block(x)\n",
    "        return res + out"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ResDNN(nn.Module):\n",
    "    '''\n",
    "    Residual Deep Neural Network \n",
    "    '''\n",
    "    def __init__(self, dim_in, dim_out, dim_hidden, res_blocks,\n",
    "                 act_name = 'tanh', init_name = 'kaiming_normal'):\n",
    "        super().__init__()\n",
    "        \n",
    "        model = nn.Sequential()\n",
    "        model.add_module('fc_first', nn.Linear(dim_in, dim_hidden, bias = True))\n",
    "        \n",
    "        for i in range(res_blocks):\n",
    "            res_block = ResBlock(dim_hidden, dim_hidden, dim_hidden, act_name = act_name)\n",
    "            model.add_module(f'res_block{i+1}', res_block)\n",
    "        \n",
    "        model.add_module('act_last', activation(act_name))\n",
    "        model.add_module('fc_last', nn.Linear(dim_hidden, dim_out, bias = True))\n",
    "        \n",
    "        self.model = model\n",
    "        \n",
    "        if init_name is not None:\n",
    "            self.init_weight(init_name)\n",
    "        \n",
    "    def init_weight(self, init_name):\n",
    "        if init_name == 'xavier_normal':\n",
    "            nn_init = nn.init.xavier_normal_\n",
    "        elif init_name == 'xavier_uniform':\n",
    "            nn_init = nn.init.xavier_uniform_\n",
    "        elif init_name == 'kaiming_normal':\n",
    "            nn_init = nn.init.kaiming_normal_\n",
    "        elif init_name == 'kaiming_uniform':\n",
    "            nn_init =  nn.init.kaiming_uniform_\n",
    "        else:\n",
    "            raise ValueError(f'unknown initialization function: {init_name}')\n",
    "            \n",
    "        for param in self.parameters():\n",
    "            if len(param.shape) > 1:\n",
    "                nn_init(param)\n",
    "\n",
    "    def forward(self, x):\n",
    "        return self.model(x)         "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2、Burgers方程"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "考虑一维Burgers方程：\n",
    "$$\n",
    "\\left\\{\n",
    "\\begin{array}{rl}\n",
    "u_t + uu_x - \\frac{0.01}\\pi u_{xx} = 0, & x \\in[-1, 1], ~~ t \\in [0, 1]\\\\\n",
    "u(0, x) = - \\sin(\\pi x), & \\\\\n",
    "u(t,-1) = u(t, 1) = 0.\n",
    "\\end{array}\n",
    "\\right.\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.1、问题描述"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Problem_Burgers(object):\n",
    "    '''\n",
    "    Description of Burgers Equation\n",
    "    \n",
    "    Params\n",
    "    ====\n",
    "    x:(N,2)ndarray\n",
    "    x[:,[0]] - x , x[:,[1]]  - t\n",
    "    '''\n",
    "    \n",
    "    def __init__(self, domain = (-1, 1, 0, 1)):\n",
    "        self.domain = domain\n",
    "        \n",
    "    def __repr__(self):\n",
    "        return f'{self.__doc__}'\n",
    "    \n",
    "    def f(self, x, verbose = None):\n",
    "        out = np.zeros_like(x[:,[0]])\n",
    "        if verbose == 'tensor':\n",
    "            return torch.from_numpy(out).float().cuda()\n",
    "        return out\n",
    "    \n",
    "    def ic(self, x, verbose = None):\n",
    "        '''initial condition'''\n",
    "        out = - np.sin(np.pi*x[:,[0]])\n",
    "        if verbose == 'tensor':\n",
    "            return torch.from_numpy(out).float().cuda()\n",
    "        return out\n",
    "    \n",
    "    def bc(self, x, verbose = None):\n",
    "        '''Dirichlet boundary condition'''\n",
    "        out = np.zeros_like(x[:,[0]])\n",
    "        if verbose == 'tensor':\n",
    "            return torch.from_numpy(out).float().cuda()\n",
    "        return out"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2、数据集生成"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Trainset_Burgers(object):\n",
    "    def __init__(self, problem, *args, **kwargs):\n",
    "        self.problem = problem\n",
    "        self.domain = problem.domain\n",
    "        self.args = args\n",
    "        self.method = kwargs['method']\n",
    "        \n",
    "    def __call__(self, plot=False, verbose=None):\n",
    "        if self.method == 'uniform':\n",
    "            n_x, n_t = self.args[0], self.args[1]\n",
    "            x, x_ic, x_bc = self._uniform_sample(n_x, n_t)\n",
    "        elif self.method == 'lhs':\n",
    "            n, n_ic, n_bc = self.args[0], self.args[1], self.args[2]\n",
    "            x, x_ic, x_bc = self._lhs_sample(n, n_ic, n_bc)\n",
    "        f = self.problem.f(x)\n",
    "        ic = self.problem.ic(x_ic)\n",
    "        bc = self.problem.bc(x_bc)\n",
    "        \n",
    "        if plot:\n",
    "            fig = plt.figure()\n",
    "            ax = fig.add_subplot(111)\n",
    "            ax.scatter(x[:, 0], x[:, 1], facecolor='r', s=10)\n",
    "            ax.scatter(x_ic[:, 0], x_ic[:, 1], facecolor='b', s=10)\n",
    "            ax.scatter(x_bc[:, 0], x_bc[:, 1], facecolor='g', s=10)\n",
    "            ax.set_xlim(self.domain[0]-0.01, self.domain[1]+0.01)\n",
    "            ax.set_ylim(self.domain[2]-0.01, self.domain[3]+0.01)\n",
    "            ax.set_aspect('equal')\n",
    "            plt.show()\n",
    "            \n",
    "        if verbose is not None:\n",
    "            x = torch.from_numpy(x).float().cuda()\n",
    "            x_ic = torch.from_numpy(x_ic).float().cuda()\n",
    "            x_bc = torch.from_numpy(x_bc).float().cuda()\n",
    "            f = torch.from_numpy(f).float().cuda()\n",
    "            ic = torch.from_numpy(ic).float().cuda()\n",
    "            bc = torch.from_numpy(bc).float().cuda()\n",
    "            return x, x_ic, x_bc, f, ic, bc\n",
    "        return x, x_ic, x_bc, f, ic, bc\n",
    "        \n",
    "    def _uniform_sample(self, n_x, n_t):\n",
    "        x_min, x_max, t_min, t_max = self.domain\n",
    "        x = np.linspace(x_min, x_max, n_x)\n",
    "        t = np.linspace(t_min, t_max, n_t)\n",
    "        x, t = np.meshgrid(x, t)\n",
    "        xt = np.hstack((x.reshape(x.size, -1), t.reshape(t.size, -1)))\n",
    "        \n",
    "        mask1 =  (xt[:, 1] - t_min) == 0\n",
    "        x_ic =xt[mask1]\n",
    "        \n",
    "        mask2 = (xt[:, 0] - x_min) * (x_max - xt[:, 0])== 0\n",
    "        x_bc = xt[mask2]\n",
    "        x = xt[np.logical_not(mask1 + mask2)]\n",
    "\n",
    "        return x, x_ic, x_bc\n",
    "        \n",
    "    def _lhs_sample(self, n, n_ic, n_bc):\n",
    "        x_min, x_max, t_min, t_max = self.domain\n",
    "\n",
    "        lb = np.array([x_min, t_min])\n",
    "        ub = np.array([x_max, t_max])\n",
    "        x = lb + (ub - lb) * lhs(2, n)\n",
    "\n",
    "        lb = np.array([x_min, t_min])\n",
    "        ub = np.array([x_max, t_min])\n",
    "        x_ic = lb + (ub - lb) * lhs(2, n_ic)\n",
    "\n",
    "        lb = np.array([x_min, t_min])\n",
    "        ub = np.array([x_min, t_max])\n",
    "        x_bc = lb + (ub - lb) * lhs(2, n_bc//2)\n",
    "\n",
    "        lb = np.array([x_max, t_min])\n",
    "        ub = np.array([x_max, t_max])\n",
    "        temp = lb + (ub - lb) * lhs(2, n_bc//2)\n",
    "        x_bc = np.vstack((x_bc, temp))\n",
    "        \n",
    "        return x, x_ic, x_bc"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Testset_Burgers(object):\n",
    "    \"\"\"Dataset on a square domain\"\"\"\n",
    "    def __init__(self, problem, *args, **kwargs):\n",
    "        self.problem = problem\n",
    "        self.domain = problem.domain\n",
    "        self.args = args\n",
    "        self.method = kwargs['method']\n",
    "\n",
    "    def __repr__(self):\n",
    "        return f'{self.__doc__}'\n",
    "        \n",
    "    def __call__(self, plot=False, verbose=None):\n",
    "        if self.method == 'uniform':\n",
    "            n_x, n_t = self.args[0], self.args[1]\n",
    "            X, x, t = self._uniform_sample(n_x, n_t)\n",
    "        \n",
    "        if plot == True:\n",
    "            fig = plt.figure()\n",
    "            ax = fig.add_subplot(111)\n",
    "            ax.scatter(X[:, 0], X[:, 1], facecolor='r', s=10)\n",
    "            ax.set_xlim(self.domain[0]-0.01, self.domain[1]+0.01)\n",
    "            ax.set_ylim(self.domain[2]-0.01, self.domain[3]+0.01)\n",
    "            ax.set_aspect('equal')\n",
    "            plt.show() \n",
    "            \n",
    "        if verbose == 'tensor':\n",
    "            X = torch.from_numpy(X).float().cuda() \n",
    "        return X, x, t\n",
    "\n",
    "    def _uniform_sample(self, n_x, n_t):\n",
    "        x_min, x_max, t_min, t_max = self.domain\n",
    "        x = np.linspace(x_min, x_max, n_x)\n",
    "        t = np.linspace(t_min, t_max, n_t)\n",
    "        x, t = np.meshgrid(x, t)\n",
    "        X = np.hstack((x.reshape(x.size, -1), t.reshape(t.size, -1)))\n",
    "        return X, x, t\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.3、网络结构"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def grad(outputs, inputs):\n",
    "    return torch.autograd.grad(outputs, inputs, grad_outputs=torch.ones_like(outputs), create_graph=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "class PINN_Burgers(DNN):\n",
    "    '''\n",
    "    Physics Constrained Neural Networks\n",
    "    '''\n",
    "    def __init__(self, dim_in, dim_out, dim_hidden, hidden_layers, act_name = 'tanh', init_name = 'xavier_normal'):\n",
    "        super().__init__(dim_in, dim_out, dim_hidden, hidden_layers, act_name = act_name, init_name = init_name)\n",
    "        \n",
    "    def forward(self, x, x_ic = None, x_bc=None):\n",
    "        x.requires_grad_(True)\n",
    "        u = super().forward(x)\n",
    "\n",
    "        grad_u = grad(u, x)[0]        \n",
    "        u_x = grad_u[:, [0]]\n",
    "        u_t = grad_u[:, [1]]\n",
    "        u_xx = grad(u_x, x)[0][:, [0]]\n",
    "\n",
    "        x.detach_()   \n",
    "\n",
    "        f = u_t + u*u_x - (0.01/np.pi)*u_xx\n",
    "        \n",
    "        if x_ic is not None:\n",
    "            if x_bc is not None:\n",
    "                ic = super().forward(x_ic)\n",
    "                bc = super().forward(x_bc)\n",
    "                return u, f, ic, bc\n",
    "            else:\n",
    "                ic = super().forward(x_ic)\n",
    "                return u, f, ic\n",
    "        elif x_bc is not None:\n",
    "            bc = super().forward(x_bc)\n",
    "            return u, f, bc\n",
    "        return u, f"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ResPINN_Burgers(ResDNN):\n",
    "    '''\n",
    "    Physics Constrained Neural Networks\n",
    "    '''\n",
    "    def __init__(self, dim_in, dim_out, dim_hidden, res_blocks, act_name = 'tanh', init_name = 'xavier_normal'):\n",
    "        super().__init__(dim_in, dim_out, dim_hidden, res_blocks, act_name = act_name, init_name = init_name)\n",
    "        \n",
    "    def forward(self, x, x_ic = None, x_bc=None):\n",
    "        x.requires_grad_(True)\n",
    "        u = super().forward(x)\n",
    "\n",
    "        grad_u = grad(u, x)[0]        \n",
    "        u_x = grad_u[:, [0]]\n",
    "        u_t = grad_u[:, [1]]\n",
    "        u_xx = grad(u_x, x)[0][:, [0]]\n",
    "\n",
    "        x.detach_()   \n",
    "\n",
    "        f = u_t + u*u_x - (0.01/np.pi)*u_xx\n",
    "        \n",
    "        if x_ic is not None:\n",
    "            if x_bc is not None:\n",
    "                ic = super().forward(x_ic)\n",
    "                bc = super().forward(x_bc)\n",
    "                return u, f, ic, bc\n",
    "            else:\n",
    "                ic = super().forward(x_ic)\n",
    "                return u, f, ic\n",
    "        elif x_bc is not None:\n",
    "            bc = super().forward(x_bc)\n",
    "            return u, f, bc\n",
    "        return u, f"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.4、Options"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Options_Burgers(object):\n",
    "    def __init__(self):\n",
    "        parser = argparse.ArgumentParser()\n",
    "        parser.add_argument('--no_cuda', action='store_true', default=False, help='disable CUDA or not')\n",
    "        parser.add_argument('--dim_hidden', type=int, default=20, help='neurons in hidden layers')\n",
    "        parser.add_argument('--hidden_layers', type=int, default=6, help='number of hidden layers')\n",
    "        parser.add_argument('--res_blocks', type=int, default=4, help='number of residual blocks')\n",
    "        parser.add_argument('--dropout', type=float, default=0.5, help='dropout rate')\n",
    "        parser.add_argument('--lam', type=float, default=1, help='weight in loss function')\n",
    "        parser.add_argument('--lr', type=float, default=1e-3, help='initial learning rate')\n",
    "        parser.add_argument('--epochs_Adam', type=int, default=2500, help='epochs for Adam optimizer')\n",
    "        parser.add_argument('--epochs_LBFGS', type=int, default=500, help='epochs for LBFGS optimizer')\n",
    "        parser.add_argument('--step_size', type=int, default=2000, help='step size in lr_scheduler for Adam optimizer')\n",
    "        parser.add_argument('--gamma', type=float, default=0.7, help='gamma in lr_scheduler for Adam optimizer')\n",
    "        parser.add_argument('--resume', type=bool, default=False, help='resume or not')\n",
    "        parser.add_argument('--sample_method', type=str, default='lhs', help='sample method')\n",
    "        parser.add_argument('--n_x', type=int, default=256, help='sample points in x-direction for uniform sample')\n",
    "        parser.add_argument('--n_t', type=int, default=100, help='sample points in t-direction for uniform sample')\n",
    "        parser.add_argument('--n', type=int, default=10000, help='sample points in domain for lhs sample')\n",
    "        parser.add_argument('--n_ic', type=int, default=400, help='sample points at t = 0 for lhs sample')\n",
    "        parser.add_argument('--n_bc', type=int, default=400, help='sample points on the boundary for lhs sample')\n",
    "        parser.add_argument('--case', type=int, default=1, help='problem case')\n",
    "        self.parser = parser\n",
    "        \n",
    "    def parse(self):\n",
    "        arg = self.parser.parse_args(args=[])\n",
    "        arg.cuda = not arg.no_cuda and torch.cuda.is_available()\n",
    "        arg.device = torch.device('cuda' if not arg.no_cuda and torch.cuda.is_available() else 'cpu')\n",
    "        return arg"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.5、训练过程"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Parameters of the neural networks can be learned by minimizing the mean squared error loss\n",
    "\n",
    "$$MSE = MSE_f+MSE_u$$\n",
    "\n",
    "where\n",
    "\n",
    "$$MSE_f = \\frac{1}{N_f}\\sum_{i=1}^{N_f}|f(t_f^i,x_f^i)|^2,\\quad MSE_u = \\frac{1}{N_u}\\sum_{i=1}^{N_u}|u(t_u^i,x_u^i)-u^i|^2$$\n",
    "\n",
    "Here, $\\{t_u^i,x_u^i,u^i\\}_{i=1}^{N_u}$ denote the initial and boundary training data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "def save_model_Burgers(state, is_best=None, save_dir=None):\n",
    "    last_model = os.path.join(save_dir, 'last_model_Burgers.pth.tar')\n",
    "    torch.save(state, last_model)\n",
    "    if is_best:\n",
    "        best_model = os.path.join(save_dir, 'best_model_Burgers.pth.tar')\n",
    "        shutil.copyfile(last_model, best_model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Trainer_Burgers(object):\n",
    "    def __init__(self, args):\n",
    "        self.device  = args.device\n",
    "        print(f'Working device: {self.device}')\n",
    "        \n",
    "        self.lam = args.lam\n",
    "        self.criterion = nn.MSELoss()\n",
    "        \n",
    "        self.model = args.model\n",
    "        self.model_name = self.model.__class__.__name__\n",
    "        self.model_path = self._model_path()\n",
    "                \n",
    "        self.epochs_Adam = args.epochs_Adam\n",
    "        self.epochs_LBFGS = args.epochs_LBFGS\n",
    "        self.optimizer_Adam = optim.Adam(self.model.parameters(), lr=args.lr)\n",
    "        self.optimizer_LBFGS = optim.LBFGS(self.model.parameters(), max_iter=20, tolerance_grad=1.e-8, tolerance_change=1.e-12)\n",
    "        self.lr_scheduler = StepLR(self.optimizer_Adam, step_size=args.step_size, gamma=args.gamma)\n",
    "\n",
    "        self.model.to(self.device)\n",
    "        self.model.zero_grad()\n",
    "        \n",
    "        self.x,     self.x_ic,     self.x_bc,     self.f,     self.ic,     self.bc     = args.trainset(verbose='tensor')\n",
    "        self.x_val, self.x_ic_val, self.x_bc_val, self.f_val, self.ic_val, self.bc_val = args.validset(verbose='tensor')\n",
    "        \n",
    "        if self.device == torch.device(type='cuda'):\n",
    "            for item in [self.x,     self.x_ic,     self.x_bc,     self.f,     self.ic,     self.bc    ]:\n",
    "                item = item.to(self.device)\n",
    "            for item in [self.x_val, self.x_ic_val, self.x_bc_val, self.f_val, self.ic_val, self.bc_val]:\n",
    "                item = item.to(self.device)\n",
    "                \n",
    "        ic_bc_points = np.vstack([self.x_ic.clone().detach().cpu(), self.x_bc.clone().detach().cpu()])\n",
    "        np.save('ic_bc_points_Burgers.npy',ic_bc_points)\n",
    "        \n",
    "    def _model_path(self):\n",
    "        \"\"\"Path to save the model\"\"\"\n",
    "        if not os.path.exists('checkpoints'):\n",
    "            os.mkdir('checkpoints')\n",
    "\n",
    "        path = os.path.join('checkpoints', self.model_name)\n",
    "        if not os.path.exists(path):\n",
    "            os.mkdir(path)\n",
    "    \n",
    "        return path\n",
    "\n",
    "    def train_Adam(self):\n",
    "        self.optimizer_Adam.zero_grad()\n",
    "\n",
    "        _, f_pred, ic_pred, bc_pred = self.model(self.x, self.x_ic, self.x_bc)\n",
    "        loss1 = self.criterion(f_pred, self.f)\n",
    "        loss2 = self.criterion(ic_pred, self.ic)\n",
    "        loss3 = self.criterion(bc_pred, self.bc)\n",
    "        loss = loss1 + self.lam * (loss2 + loss3)\n",
    "\n",
    "        loss.backward()\n",
    "        self.optimizer_Adam.step()\n",
    "        self.lr_scheduler.step()\n",
    "\n",
    "        return loss.item(), loss1.item(), loss2.item(), loss3.item()\n",
    "\n",
    "    def infos_Adam(self, epoch, loss, loss1, loss2, loss3):\n",
    "        infos = 'Adam  ' + \\\n",
    "            f'Epoch #{epoch:5d}/{self.epochs_Adam+self.epochs_LBFGS} ' + \\\n",
    "            f'Loss: {loss:.4e} = {loss1:.4e} + {self.lam} * ({loss2:.4e}+{loss3:.4e}) ' + \\\n",
    "            f'lr: {self.lr_scheduler.get_lr()[0]:.2e} '\n",
    "        print(infos)\n",
    "        \n",
    "    def train_LBFGS(self):\n",
    "\n",
    "        # only used to compute loss_int and loss_bc1 for monitoring\n",
    "        _, f_pred, ic_pred, bc_pred = self.model(self.x, self.x_ic, self.x_bc)\n",
    "        loss1 = self.criterion(f_pred, self.f)\n",
    "        loss2 = self.criterion(ic_pred, self.ic)\n",
    "        loss3 = self.criterion(bc_pred, self.bc)\n",
    "        \n",
    "        def closure():\n",
    "            if torch.is_grad_enabled():\n",
    "                self.optimizer_LBFGS.zero_grad()\n",
    "            _, f_pred, ic_pred, bc_pred = self.model(self.x, self.x_ic, self.x_bc)\n",
    "            loss1 = self.criterion(f_pred, self.f)\n",
    "            loss2 = self.criterion(ic_pred, self.ic)\n",
    "            loss3 = self.criterion(bc_pred, self.bc)\n",
    "            loss = loss1 + self.lam * (loss2 + loss3)\n",
    "            if loss.requires_grad:\n",
    "                loss.backward()\n",
    "            return loss\n",
    "\n",
    "        self.optimizer_LBFGS.step(closure)\n",
    "        loss = closure()\n",
    "\n",
    "        return loss.item(), loss1.item(), loss2.item(), loss3.item()\n",
    "        \n",
    "    def infos_LBFGS(self, epoch, loss, loss1, loss2, loss3):\n",
    "        infos = 'LBFGS ' + \\\n",
    "            f'Epoch #{epoch:5d}/{self.epochs_Adam+self.epochs_LBFGS} ' + \\\n",
    "            f'Loss: {loss:.2e} = {loss1:.2e} + {self.lam:d} * ({loss2:.4e}+{loss3:.4e}) '\n",
    "        print(infos)\n",
    "\n",
    "    def validate(self, epoch):\n",
    "        self.model.eval()\n",
    "        _, f_pred, ic_pred, bc_pred = self.model(self.x_val, self.x_ic_val, self.x_bc_val)\n",
    "        loss1 = self.criterion(f_pred, self.f_val)\n",
    "        loss2 = self.criterion(ic_pred, self.ic_val)\n",
    "        loss3 = self.criterion(bc_pred, self.bc_val)\n",
    "        loss = loss1 + self.lam * (loss2 + loss3)\n",
    "        \n",
    "        infos = 'Valid ' + \\\n",
    "            f'Epoch #{epoch+1:5d}/{self.epochs_Adam+self.epochs_LBFGS} ' + \\\n",
    "            f'Loss: {loss:.4e} '\n",
    "        print(infos)\n",
    "        self.model.train()\n",
    "        return loss.item()\n",
    "\n",
    "    def train(self):\n",
    "        best_loss = 1.e10\n",
    "        train_losses_index = []\n",
    "        train_losses = []\n",
    "        valid_losses_index = []\n",
    "        valid_losses = []\n",
    "        \n",
    "        for epoch in range(self.epochs_Adam):\n",
    "            loss, loss1, loss2, loss3 = self.train_Adam()\n",
    "            train_losses_index += [epoch]\n",
    "            train_losses += [loss]\n",
    "            \n",
    "            if (epoch + 1) % 100 == 0:\n",
    "                self.infos_Adam(epoch+1, loss, loss1, loss2, loss3)\n",
    "                \n",
    "                valid_loss = self.validate(epoch)\n",
    "                is_best = valid_loss < best_loss\n",
    "                best_loss = valid_loss if is_best else best_loss                \n",
    "                state = {\n",
    "                    'epoch': epoch,\n",
    "                    'state_dict': self.model.state_dict(),\n",
    "                    'best_loss': best_loss\n",
    "                }\n",
    "                save_model_Burgers(state, is_best, save_dir=self.model_path)\n",
    "                valid_losses_index += [epoch]\n",
    "                valid_losses += [valid_loss]\n",
    "            \n",
    "        for epoch in range(self.epochs_Adam, self.epochs_Adam + self.epochs_LBFGS):\n",
    "            loss, loss1, loss2, loss3 = self.train_LBFGS()\n",
    "            train_losses_index += [epoch]\n",
    "            train_losses += [loss]\n",
    "            \n",
    "            if (epoch + 1) % 20 == 0:\n",
    "                self.infos_LBFGS(epoch+1, loss, loss1, loss2, loss3)\n",
    "                \n",
    "                valid_loss = self.validate(epoch)\n",
    "                is_best = valid_loss < best_loss\n",
    "                best_loss = valid_loss if is_best else best_loss                \n",
    "                state = {\n",
    "                    'epoch': epoch,\n",
    "                    'state_dict': self.model.state_dict(),\n",
    "                    'best_loss': best_loss\n",
    "                }\n",
    "                save_model_Burgers(state, is_best, save_dir=self.model_path)\n",
    "                valid_losses_index += [epoch]\n",
    "                valid_losses += [valid_loss]\n",
    "\n",
    "        # save loss curve info\n",
    "        np.save('Burgers_loss.npy',[train_losses_index,train_losses,valid_losses_index,valid_losses])\n",
    "        \n",
    "        # loss curve\n",
    "        fig = plt.figure(figsize=(10,5))\n",
    "        ax = fig.add_subplot(111)\n",
    "        ax.set_title('Loss curve',usetex = True,fontsize=20)\n",
    "        ax.set_yscale(\"log\")\n",
    "        ax.set_xlabel('epoch',usetex = True,fontsize=20)\n",
    "        ax.set_ylabel('loss',usetex = True,fontsize=20)\n",
    "        ax.plot(train_losses_index, train_losses, color = 'g', label = 'train loss')\n",
    "        ax.plot(valid_losses_index, valid_losses, color = 'r', linestyle='--', label = 'valid loss')\n",
    "        ax.legend(frameon=False, loc = 'best')\n",
    "        plt.savefig('Burgers_train')\n",
    "        plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Working device: cuda\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "d:\\program files (x86)\\python\\lib\\site-packages\\torch\\optim\\lr_scheduler.py:351: UserWarning: To get the last learning rate computed by the scheduler, please use `get_last_lr()`.\n",
      "  \"please use `get_last_lr()`.\", UserWarning)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Adam  Epoch #  100/3000 Loss: 1.6161e-01 = 5.2081e-02 + 1 * (9.7494e-02+1.2037e-02) lr: 1.00e-03 \n",
      "Valid Epoch #  100/3000 Loss: 1.6083e-01 \n",
      "Adam  Epoch #  200/3000 Loss: 1.4059e-01 = 5.4297e-02 + 1 * (8.0346e-02+5.9460e-03) lr: 1.00e-03 \n",
      "Valid Epoch #  200/3000 Loss: 1.4034e-01 \n",
      "Adam  Epoch #  300/3000 Loss: 1.2422e-01 = 5.0384e-02 + 1 * (7.0600e-02+3.2323e-03) lr: 1.00e-03 \n",
      "Valid Epoch #  300/3000 Loss: 1.2384e-01 \n",
      "Adam  Epoch #  400/3000 Loss: 1.0870e-01 = 4.6047e-02 + 1 * (6.1423e-02+1.2299e-03) lr: 1.00e-03 \n",
      "Valid Epoch #  400/3000 Loss: 1.0893e-01 \n",
      "Adam  Epoch #  500/3000 Loss: 1.0173e-01 = 4.3397e-02 + 1 * (5.7738e-02+6.0006e-04) lr: 1.00e-03 \n",
      "Valid Epoch #  500/3000 Loss: 1.0167e-01 \n",
      "Adam  Epoch #  600/3000 Loss: 9.7282e-02 = 4.1445e-02 + 1 * (5.5367e-02+4.6970e-04) lr: 1.00e-03 \n",
      "Valid Epoch #  600/3000 Loss: 9.7129e-02 \n",
      "Adam  Epoch #  700/3000 Loss: 9.1701e-02 = 3.9163e-02 + 1 * (5.2258e-02+2.7951e-04) lr: 1.00e-03 \n",
      "Valid Epoch #  700/3000 Loss: 9.2626e-02 \n",
      "Adam  Epoch #  800/3000 Loss: 8.5696e-02 = 3.6045e-02 + 1 * (4.9500e-02+1.5073e-04) lr: 1.00e-03 \n",
      "Valid Epoch #  800/3000 Loss: 8.7811e-02 \n",
      "Adam  Epoch #  900/3000 Loss: 8.1466e-02 = 3.3364e-02 + 1 * (4.7997e-02+1.0466e-04) lr: 1.00e-03 \n",
      "Valid Epoch #  900/3000 Loss: 8.3012e-02 \n",
      "Adam  Epoch # 1000/3000 Loss: 7.5065e-02 = 3.0263e-02 + 1 * (4.4699e-02+1.0350e-04) lr: 1.00e-03 \n",
      "Valid Epoch # 1000/3000 Loss: 7.7084e-02 \n",
      "Adam  Epoch # 1100/3000 Loss: 6.2548e-02 = 2.6062e-02 + 1 * (3.6406e-02+8.0081e-05) lr: 1.00e-03 \n",
      "Valid Epoch # 1100/3000 Loss: 6.3976e-02 \n",
      "Adam  Epoch # 1200/3000 Loss: 4.4155e-02 = 2.0488e-02 + 1 * (2.3427e-02+2.3987e-04) lr: 1.00e-03 \n",
      "Valid Epoch # 1200/3000 Loss: 4.5774e-02 \n",
      "Adam  Epoch # 1300/3000 Loss: 3.1898e-02 = 1.4997e-02 + 1 * (1.6777e-02+1.2419e-04) lr: 1.00e-03 \n",
      "Valid Epoch # 1300/3000 Loss: 3.3033e-02 \n",
      "Adam  Epoch # 1400/3000 Loss: 2.5661e-02 = 1.3433e-02 + 1 * (1.1733e-02+4.9448e-04) lr: 1.00e-03 \n",
      "Valid Epoch # 1400/3000 Loss: 2.2369e-02 \n",
      "Adam  Epoch # 1500/3000 Loss: 1.4301e-02 = 7.5793e-03 + 1 * (6.7008e-03+2.0568e-05) lr: 1.00e-03 \n",
      "Valid Epoch # 1500/3000 Loss: 1.5093e-02 \n",
      "Adam  Epoch # 1600/3000 Loss: 1.1112e-02 = 6.2331e-03 + 1 * (4.8549e-03+2.3760e-05) lr: 1.00e-03 \n",
      "Valid Epoch # 1600/3000 Loss: 1.2220e-02 \n",
      "Adam  Epoch # 1700/3000 Loss: 1.3370e-02 = 8.5603e-03 + 1 * (4.3284e-03+4.8143e-04) lr: 1.00e-03 \n",
      "Valid Epoch # 1700/3000 Loss: 1.0758e-02 \n",
      "Adam  Epoch # 1800/3000 Loss: 7.9984e-03 = 4.5816e-03 + 1 * (3.3948e-03+2.1998e-05) lr: 1.00e-03 \n",
      "Valid Epoch # 1800/3000 Loss: 8.8436e-03 \n",
      "Adam  Epoch # 1900/3000 Loss: 6.8919e-03 = 3.9525e-03 + 1 * (2.9210e-03+1.8460e-05) lr: 1.00e-03 \n",
      "Valid Epoch # 1900/3000 Loss: 7.6328e-03 \n",
      "Adam  Epoch # 2000/3000 Loss: 1.3958e-02 = 5.4354e-03 + 1 * (7.4141e-03+1.1089e-03) lr: 4.90e-04 \n",
      "Valid Epoch # 2000/3000 Loss: 1.4619e-02 \n",
      "Adam  Epoch # 2100/3000 Loss: 6.0253e-03 = 3.0764e-03 + 1 * (2.9326e-03+1.6270e-05) lr: 7.00e-04 \n",
      "Valid Epoch # 2100/3000 Loss: 7.0442e-03 \n",
      "Adam  Epoch # 2200/3000 Loss: 5.3643e-03 = 2.8207e-03 + 1 * (2.5296e-03+1.3912e-05) lr: 7.00e-04 \n",
      "Valid Epoch # 2200/3000 Loss: 6.4993e-03 \n",
      "Adam  Epoch # 2300/3000 Loss: 4.9420e-03 = 2.6203e-03 + 1 * (2.3093e-03+1.2404e-05) lr: 7.00e-04 \n",
      "Valid Epoch # 2300/3000 Loss: 6.0694e-03 \n",
      "Adam  Epoch # 2400/3000 Loss: 4.5705e-03 = 2.4249e-03 + 1 * (2.1347e-03+1.0890e-05) lr: 7.00e-04 \n",
      "Valid Epoch # 2400/3000 Loss: 5.6480e-03 \n",
      "Adam  Epoch # 2500/3000 Loss: 4.2249e-03 = 2.2408e-03 + 1 * (1.9745e-03+9.5187e-06) lr: 7.00e-04 \n",
      "Valid Epoch # 2500/3000 Loss: 5.2376e-03 \n",
      "LBFGS Epoch # 2520/3000 Loss: 3.98e-04 = 2.99e-04 + 1 * (1.1719e-04+1.5471e-06) \n",
      "Valid Epoch # 2520/3000 Loss: 4.6970e-04 \n",
      "LBFGS Epoch # 2540/3000 Loss: 1.51e-04 = 1.08e-04 + 1 * (4.6999e-05+1.6164e-06) \n",
      "Valid Epoch # 2540/3000 Loss: 2.3982e-04 \n",
      "LBFGS Epoch # 2560/3000 Loss: 6.53e-05 = 5.14e-05 + 1 * (1.5573e-05+4.3368e-07) \n",
      "Valid Epoch # 2560/3000 Loss: 2.0854e-04 \n",
      "LBFGS Epoch # 2580/3000 Loss: 4.02e-05 = 3.24e-05 + 1 * (8.5043e-06+1.5833e-07) \n",
      "Valid Epoch # 2580/3000 Loss: 1.3452e-04 \n",
      "LBFGS Epoch # 2600/3000 Loss: 2.63e-05 = 2.29e-05 + 1 * (3.6416e-06+1.3932e-07) \n",
      "Valid Epoch # 2600/3000 Loss: 1.1930e-04 \n",
      "LBFGS Epoch # 2620/3000 Loss: 1.83e-05 = 1.63e-05 + 1 * (2.2348e-06+1.7350e-07) \n",
      "Valid Epoch # 2620/3000 Loss: 8.5283e-05 \n",
      "LBFGS Epoch # 2640/3000 Loss: 1.39e-05 = 1.24e-05 + 1 * (1.6391e-06+9.3458e-08) \n",
      "Valid Epoch # 2640/3000 Loss: 7.9792e-05 \n",
      "LBFGS Epoch # 2660/3000 Loss: 1.10e-05 = 9.75e-06 + 1 * (1.3585e-06+8.2455e-08) \n",
      "Valid Epoch # 2660/3000 Loss: 7.0214e-05 \n",
      "LBFGS Epoch # 2680/3000 Loss: 8.81e-06 = 7.94e-06 + 1 * (9.1840e-07+6.2191e-08) \n",
      "Valid Epoch # 2680/3000 Loss: 5.2892e-05 \n",
      "LBFGS Epoch # 2700/3000 Loss: 6.97e-06 = 6.36e-06 + 1 * (6.5352e-07+2.8758e-08) \n",
      "Valid Epoch # 2700/3000 Loss: 3.7661e-05 \n",
      "LBFGS Epoch # 2720/3000 Loss: 5.66e-06 = 5.28e-06 + 1 * (4.1236e-07+1.8999e-08) \n",
      "Valid Epoch # 2720/3000 Loss: 3.1121e-05 \n",
      "LBFGS Epoch # 2740/3000 Loss: 5.27e-06 = 4.88e-06 + 1 * (3.6205e-07+2.3652e-08) \n",
      "Valid Epoch # 2740/3000 Loss: 3.2679e-05 \n",
      "LBFGS Epoch # 2760/3000 Loss: 5.26e-06 = 4.88e-06 + 1 * (3.6173e-07+2.3308e-08) \n",
      "Valid Epoch # 2760/3000 Loss: 3.2653e-05 \n",
      "LBFGS Epoch # 2780/3000 Loss: 5.26e-06 = 4.87e-06 + 1 * (3.6129e-07+2.3072e-08) \n",
      "Valid Epoch # 2780/3000 Loss: 3.2632e-05 \n",
      "LBFGS Epoch # 2800/3000 Loss: 5.25e-06 = 4.87e-06 + 1 * (3.6088e-07+2.2938e-08) \n",
      "Valid Epoch # 2800/3000 Loss: 3.2612e-05 \n",
      "LBFGS Epoch # 2820/3000 Loss: 5.25e-06 = 4.87e-06 + 1 * (3.6040e-07+2.2827e-08) \n",
      "Valid Epoch # 2820/3000 Loss: 3.2590e-05 \n",
      "LBFGS Epoch # 2840/3000 Loss: 5.24e-06 = 4.86e-06 + 1 * (3.5999e-07+2.2750e-08) \n",
      "Valid Epoch # 2840/3000 Loss: 3.2577e-05 \n",
      "LBFGS Epoch # 2860/3000 Loss: 5.24e-06 = 4.86e-06 + 1 * (3.5949e-07+2.2682e-08) \n",
      "Valid Epoch # 2860/3000 Loss: 3.2562e-05 \n",
      "LBFGS Epoch # 2880/3000 Loss: 5.24e-06 = 4.86e-06 + 1 * (3.5910e-07+2.2647e-08) \n",
      "Valid Epoch # 2880/3000 Loss: 3.2548e-05 \n",
      "LBFGS Epoch # 2900/3000 Loss: 5.23e-06 = 4.85e-06 + 1 * (3.5871e-07+2.2617e-08) \n",
      "Valid Epoch # 2900/3000 Loss: 3.2540e-05 \n",
      "LBFGS Epoch # 2920/3000 Loss: 5.23e-06 = 4.85e-06 + 1 * (3.5832e-07+2.2548e-08) \n",
      "Valid Epoch # 2920/3000 Loss: 3.2531e-05 \n",
      "LBFGS Epoch # 2940/3000 Loss: 5.23e-06 = 4.85e-06 + 1 * (3.5786e-07+2.2510e-08) \n",
      "Valid Epoch # 2940/3000 Loss: 3.2520e-05 \n",
      "LBFGS Epoch # 2960/3000 Loss: 5.22e-06 = 4.84e-06 + 1 * (3.5743e-07+2.2467e-08) \n",
      "Valid Epoch # 2960/3000 Loss: 3.2513e-05 \n",
      "LBFGS Epoch # 2980/3000 Loss: 5.22e-06 = 4.84e-06 + 1 * (3.5704e-07+2.2412e-08) \n",
      "Valid Epoch # 2980/3000 Loss: 3.2507e-05 \n",
      "LBFGS Epoch # 3000/3000 Loss: 5.22e-06 = 4.84e-06 + 1 * (3.5669e-07+2.2395e-08) \n",
      "Valid Epoch # 3000/3000 Loss: 3.2501e-05 \n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAnEAAAFYCAYAAAA8xqpbAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjMsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+AADFEAAAgAElEQVR4nOzdd3hUVf7H8fdJb6SRhF4FQSBIiYhgAQVFFHtBwb6AZd21Y9mfZVkFXV17QxddV0QRVwVERRAEO0WqICW0JEBIQgKBFJKc3x83gSQkISSTTCbzeT3PPDNz751zvzc+q589555zjbUWEREREfEsPu4uQERERESOn0KciIiIiAdSiBMRERHxQApxIiIiIh5IIU5ERETEAynEiYiIiHgghTgR8QjGmCHGGGuMGevuWkREGgKFOBEREREPpBAnIiIi4oEU4kREREQ8kEKciIiIiAdSiBORRscY08cY803xRIhl5SdDGGOuMMZsLt6/1xjzsTGm47H2Hcd59xa/vjHG9Cne97QxxpY7fmzxeSJLbXvAGLOs1G82G2PeLP/bKn5/RfE1l1x7n+P524mI51CIE5FGxRhzBbAMWA4MBd4EnjbGvFm8vyPwMTAD6AuMATKAyKr2VeO8Q4rPm1n8uzHFn4cc5yU0BToWB7kriusvqf2KcseOA5ZbazOL9z9QXP9Hxde+FFhWOuSJSOPh5+4CRERc7C3gGWvt+JINxphE4JviIFfSqzaxOPwsxwltpUPSUfuq4U1gnrX2ylLbqvvb8iKBDGtt31LXkAlcXarWSKAPTpAr+f40MN5a+0zxz+YZYxKAscAziEijop44EWk0invDIinuuSphrZ2H0yt2NTCvePP84qHL0sONVe2r6rwdccLh07Wpv5xx5b5PxumZK1EyRDy9+D2h+P3p4qFUWzwE2wenV05EGhmFOBFpTEp62TIq2JcI9CnuYSsJNU/jDDd+A1DVvmMoCXuJNaq6Atba8m19BGV6C6/G6fnLLP5eMmR6AhBV7lW6d1BEGgmFOBFpTEqCT0UTETqW7LfWziseqjwBGA8MKb6frMp9NTyvS1hrlxef5+riTX0o2+O4vPg90lqbWf5VV3WJiPsoxIlIY7IUZ9i0zFBkce9VJM5N/4dZaxOL7x9bDpxS3X3lFQeso85bfO6qJhX0rWJfRd7ECZVXFJ/38D13xT13icBDx1mDiHgoTWwQEU/Tt/jet/KWWmszjTFjgI+NMeCEtj44Q6MzrLXzipcbGYcTiBJxes/6AG9Wta8adV2JM3ni4+LjI3F6zSJxhmjTwVkWBOfeuyEcua+tumYUX8tDVDxpYlwFNYwrvpajAqaIeDZj7VFLD4mINDjFwa2q+9OGFk9gKDn2aZwAlgi8WTJjs3gSwjicSQIlQ6wzrLXjq9pXzRpLAuOQ4t8ux5ktmljcGza/VE0zgM04Q7Z9Sy0T8jTwgLXWVHKOZcVtXFm6J66SGjJxJj6M15CqSOOjECciIiLigXRPnIiIiIgHUogTERER8UAKcSIiIiIeSCFORERExAN55RIjMTExtn379u4uQ0REROSYli1blmatjS2/3StDXPv27Vm6dKm7yxARERE5JmPMtoq2azhVRERExAN5VYgzxowwxkzOyspydykiIiIiteJVIc5aO8taOzYiIsLdpYiIiIjUileFOBEREZHGQiFORERExAMpxImIiIh4IIU4EREREQ/kVSFOs1NFRESksfCqEKfZqSIiIo1PZmYmr732Wo1+O3z4cDIzM6t9/OOPP86zzz5bo3O5mleFuPqSdjCN1AOp7i5DRETEK1QV4goLC6v87Zw5c4iMjKyLsuqcQlwduPjDixn1v1HuLkNERMQrPPjgg2zevJlevXpx//33s3DhQgYPHsy1115LfHw8AJdccgl9+/ale/fuTJ48+fBv27dvT1paGlu3buWkk05izJgxdO/enXPPPZecnJwqz7tixQr69+9Pz549ufTSS9m7dy8AL730Et26daNnz56MHDkSgO+++45evXrRq1cvevfuzf79+2t93V757NS6FuAbQF5BnrvLEBERqXd3fXUXK3atcGmbvZr34oVhL1S6f9KkSaxZs4YVK5zzLly4kF9//ZU1a9bQoUMHAKZMmUJ0dDQ5OTmccsopXH755TRt2rRMOxs3bmTatGm89dZbXHXVVXzyySeMHj260vNef/31vPzyy5x11lk8+uijPPHEE7zwwgtMmjSJLVu2EBgYeHio9tlnn+XVV19l4MCBZGdnExQUVNs/i3ri6kKAbwD5hfnuLkNERMRr9evX73CAA6d37OSTT6Z///7s2LGDjRs3HvWbDh060KtXLwD69u3L1q1bK20/KyuLzMxMzjrrLABuuOEG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\n",
      "text/plain": [
       "<Figure size 720x360 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 使用Trainer_Burgers进行训练\n",
    "args = Options_Burgers().parse()\n",
    "args.problem = Problem_Burgers()\n",
    "\n",
    "#args.model = PINN_Burgers(2, 1, dim_hidden=args.dim_hidden, hidden_layers=args.hidden_layers)\n",
    "args.model = ResPINN_Burgers(2, 1, dim_hidden=args.dim_hidden, res_blocks=args.res_blocks)\n",
    "\n",
    "if args.sample_method == 'uniform':\n",
    "    args.trainset = Trainset_Burgers(args.problem, args.n_x, args.n_t, method='uniform')\n",
    "elif args.sample_method == 'lhs':\n",
    "    args.trainset = Trainset_Burgers(args.problem, args.n, args.n_ic, args.n_bc, method='lhs')\n",
    "\n",
    "args.validset = Trainset_Burgers(args.problem, 100, 100, method='uniform')\n",
    "    \n",
    "trainer = Trainer_Burgers(args)\n",
    "trainer.train()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.6、测试过程"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Tester_Burgers(object):\n",
    "    def __init__(self, args):\n",
    "        self.device  = args.device\n",
    "\n",
    "        self.criterion = nn.MSELoss()\n",
    "        self.model = args.model\n",
    "        model_name = self.model.__class__.__name__\n",
    "        model_path = os.path.join('checkpoints',\n",
    "                                  model_name,\n",
    "                                  'best_model_Burgers.pth.tar')\n",
    "        best_model = torch.load(model_path)\n",
    "        self.model.load_state_dict(best_model['state_dict'])        \n",
    "        self.model.to(self.device)\n",
    "        self.X, self.x, self.t = args.testset(verbose='tensor')\n",
    "        if self.device == torch.device(type='cuda'):\n",
    "            self.X = self.X.to(self.device)\n",
    "    \n",
    "    def predict(self):\n",
    "        self.model.eval()\n",
    "        u_pred, _ = self.model(self.X)\n",
    "        u_pred = u_pred.detach().cpu().numpy()\n",
    "        u_pred = u_pred.reshape(self.x.shape)\n",
    "        \n",
    "        n_t = u_pred.shape[0]\n",
    "        \n",
    "        # slide time index\n",
    "        n_t_1 = int(n_t*0.25 - 1)\n",
    "        n_t_2 = int(n_t*0.50 - 1)\n",
    "        n_t_3 = int(n_t*0.75 - 1)\n",
    "        \n",
    "        # Loading exact solutions:\n",
    "        data = scipy.io.loadmat('burgers_shock.mat')\n",
    "        Exact_t = data['t'].flatten()[:,None] # 256*1\n",
    "        Exact_x = data['x'].flatten()[:,None] # 100*1\n",
    "        Exact_u= np.real(data['usol'])\n",
    "\n",
    "        # u:plot\n",
    "        fig = plt.figure(figsize=(12,3))\n",
    "        ax = fig.add_subplot(111)\n",
    "        h = ax.imshow(u_pred.T, interpolation='nearest', cmap='rainbow',\n",
    "                      extent=[self.t.min(), self.t.max(), self.x.min(), self.x.max()], origin='lower', aspect='auto')\n",
    "        divider = make_axes_locatable(ax)\n",
    "        cax = divider.append_axes(\"right\", size=\"5%\", pad=0.05)\n",
    "        fig.colorbar(h, cax=cax)\n",
    "        \n",
    "        ic_bc_points = np.load('ic_bc_points_Burgers.npy')\n",
    "        ax.plot(ic_bc_points[:,1], ic_bc_points[:,0], 'kx', \n",
    "                label = 'IC and BC Data (%d points)' % (ic_bc_points.shape[0]), markersize = 4, clip_on = False)\n",
    "        ax.legend(loc='upper right',frameon=False, fontsize=12)\n",
    "    \n",
    "        line = np.linspace(self.x.min(), self.x.max(), 2)[:,None]\n",
    "        ax.plot((self.t[-1,-1]*n_t_1)/n_t*np.ones((2,1)), line, 'k--', linewidth = 2)\n",
    "        ax.plot((self.t[-1,-1]*n_t_2)/n_t*np.ones((2,1)), line, 'k--', linewidth = 2)\n",
    "        ax.plot((self.t[-1,-1]*n_t_3)/n_t*np.ones((2,1)), line, 'k--', linewidth = 2)    \n",
    "    \n",
    "        ax.set_xlabel('$t$',usetex = True,fontsize=20)\n",
    "        ax.set_ylabel('$x$',usetex = True,fontsize=20)\n",
    "        ax.set_title('$u(t,x)$',usetex = True,fontsize=20)\n",
    "        plt.savefig('Burgers_1')\n",
    "        plt.show()\n",
    "        \n",
    "        # u:slide plots\n",
    "        fig = plt.figure(figsize=(15,3))\n",
    "        ax = fig.add_subplot(131)\n",
    "        ax.plot(self.x[0,:], u_pred[n_t_1,:], linewidth = 3, label = 'Predict')       \n",
    "        ax.plot(Exact_x, Exact_u[:,n_t_1], linestyle = '--', linewidth = 3, label = 'Exact')    \n",
    "        ax.set_title('$t = %.2f$' % (self.t[n_t_1,0]),usetex = True,fontsize=20)\n",
    "        ax.set_xlabel('$x$',usetex = True,fontsize=20)\n",
    "        ax.set_ylabel('$u(t,x)$',usetex = True,fontsize=20)\n",
    "        ax.legend(frameon=False, loc = 'best')\n",
    "        ax.axis('square')\n",
    "        ax.set_xlim([-1.1,1.1])\n",
    "        ax.set_ylim([-1.1,1.1])\n",
    " \n",
    "        ax = fig.add_subplot(132)\n",
    "        ax.plot(self.x[0,:], u_pred[n_t_2,:], linewidth = 3, label = 'Predict')\n",
    "        ax.plot(Exact_x, Exact_u[:,n_t_2], linestyle = '--', linewidth = 3, label = 'Exact')  \n",
    "        ax.set_title('$t = %.2f$' % (self.t[n_t_2,0]),usetex = True,fontsize=20)\n",
    "        ax.set_xlabel('$x$',usetex = True,fontsize=20)\n",
    "        ax.set_ylabel('$u(t,x)$',usetex = True,fontsize=20)\n",
    "        ax.legend(frameon=False, loc = 'best')\n",
    "        ax.axis('square')\n",
    "        ax.set_xlim([-1.1,1.1])\n",
    "        ax.set_ylim([-1.1,1.1])\n",
    "        \n",
    "        ax = fig.add_subplot(133)\n",
    "        ax.plot(self.x[0,:], u_pred[n_t_3,:], linewidth = 3, label = 'Predict')\n",
    "        ax.plot(Exact_x, Exact_u[:,n_t_3], linestyle = '--', linewidth = 3, label = 'Exact')  \n",
    "        ax.set_title('$t = %.2f$' % (self.t[n_t_3,0]),usetex = True,fontsize=20)\n",
    "        ax.set_xlabel('$x$',usetex = True,fontsize=20)\n",
    "        ax.set_ylabel('$u(t,x)$',usetex = True,fontsize=20)\n",
    "        ax.legend(frameon=False, loc = 'best')\n",
    "        ax.axis('square')\n",
    "        ax.set_xlim([-1.1,1.1])\n",
    "        ax.set_ylim([-1.1,1.1])\n",
    "        \n",
    "        plt.savefig('Burgers_2')\n",
    "        plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 864x216 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1080x216 with 3 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 使用Tester_Burgers进行预测，复现文章中的Figure1\n",
    "args = Options_Burgers().parse()\n",
    "args.problem = Problem_Burgers()\n",
    "\n",
    "args.model = ResPINN_Burgers(2, 1, dim_hidden=args.dim_hidden, res_blocks=args.res_blocks)\n",
    "args.testset = Testset_Burgers(args.problem, args.n_x, args.n_t, method='uniform')  \n",
    "\n",
    "tester = Tester_Burgers(args)\n",
    "tester.predict()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.7、对照实验"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 对照试验代码，三组对照试验均由本节代码修改完成\n",
    "less = np.load('.\\\\B hidden layers\\\\less\\\\Burgers_loss.npy', allow_pickle=True)\n",
    "more = np.load('.\\\\B hidden layers\\\\more\\\\Burgers_loss.npy', allow_pickle=True)\n",
    "\n",
    "# loss curve\n",
    "fig = plt.figure(figsize=(10,5))\n",
    "ax = fig.add_subplot(111)\n",
    "ax.set_title('Loss curve',usetex = True,fontsize=20)\n",
    "ax.set_yscale(\"log\")\n",
    "ax.set_xlabel('epoch',usetex = True,fontsize=20)\n",
    "ax.set_ylabel('loss',usetex = True,fontsize=20)\n",
    "ax.plot(less[0], less[1], color = 'g', label = 'less hidden layers train loss')\n",
    "ax.plot(less[2], less[3], color = 'r', linestyle='--', label = 'less hidden layers valid loss')\n",
    "ax.plot(more[0], more[1], color = 'b', label = 'more hidden layers train loss')\n",
    "ax.plot(more[2], more[3], color = 'y', linestyle='--', label = 'more hidden layers valid loss')\n",
    "ax.legend(frameon=False, loc = 'best')\n",
    "plt.savefig('Burgers_train')\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2.7.1、在相同的超参数的情况下，PINN和ResPINN的比较\n",
    "两者的loss曲线对比如下：\n",
    "![jupyter](Data/B_PINN_and_ResPINN/Burgers_train.png) \n",
    "PINN的结果如下：\n",
    "![jupyter](Data/B_PINN_and_ResPINN/pinn/Burgers_2.png)\n",
    "ResPINN的结果如下：\n",
    "![jupyter](Data/B_PINN_and_ResPINN/respinn/Burgers_2.png)\n",
    "\n",
    "#### 2.7.2、固定隐藏元个数，不同隐藏层数或残差块数对训练结果的影响：\n",
    "两者的loss曲线对比如下：\n",
    "![jupyter](Data/B_hidden_layers/Burgers_train.png) \n",
    "隐藏层数为2的结果如下：\n",
    "![jupyter](Data/B_hidden_layers/less/Burgers_2.png)\n",
    "隐藏层数为4的结果如下：\n",
    "![jupyter](Data/B_hidden_layers/more/Burgers_2.png)\n",
    "\n",
    "#### 2.7.3、固定隐藏层数或残差块数，不同隐藏元个数对训练结果的影响：\n",
    "两者的loss曲线对比如下：\n",
    "![jupyter](Data/B_neurons/Burgers_train.png) \n",
    "隐藏元个数为5的结果如下：\n",
    "![jupyter](Data/B_neurons/less/Burgers_2.png)\n",
    "隐藏元个数为10的结果如下：\n",
    "![jupyter](Data/B_neurons/more/Burgers_2.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3、非线性薛定谔方程"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "考虑带周期边界条件的非线性薛定谔方程：\n",
    "$$\n",
    "\\left\\{\n",
    "\\begin{array}{rl}\n",
    "i h_t + 0.5 h_{xx} + |h|^2 h = 0, & x \\in[-5, 5], ~~ t \\in [0, \\pi/2]\\\\\n",
    "h(0, x) = 2\\mathrm{sech}(x), & \\\\\n",
    "h(t,-5) = h(t, 5), & \\\\\n",
    "h_x(t, -5) = h_x(t, 5), & \n",
    "\\end{array}\n",
    "\\right.\n",
    "$$\n",
    "其中$h(t,x)$为复值函数。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.1、问题描述"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Problem_Schrodinger(object):\n",
    "    '''\n",
    "    Description of Schrodinger Equation\n",
    "    \n",
    "    Params\n",
    "    ====\n",
    "    x:(N,2)ndarray\n",
    "    x[:,[0]] - x , x[:,[1]]  - t\n",
    "    '''\n",
    "    \n",
    "    def __init__(self, domain = (-5, 5, 0, np.pi/2)):\n",
    "        self.domain = domain\n",
    "        \n",
    "    def __repr__(self):\n",
    "        return f'{self.__doc__}'\n",
    "    \n",
    "    def f_u(self, x, verbose = None):\n",
    "        out = np.zeros_like(x[:,[0]])\n",
    "        if verbose == 'tensor':\n",
    "            return torch.from_numpy(out).float().cuda()\n",
    "        return out\n",
    "    def f_v(self, x, verbose = None):\n",
    "        out = np.zeros_like(x[:,[0]])\n",
    "        if verbose == 'tensor':\n",
    "            return torch.from_numpy(out).float().cuda()\n",
    "        return out\n",
    "    \n",
    "    def ic_u(self, x, verbose = None):\n",
    "        '''initial condition'''\n",
    "        out = 2/np.cosh(x[:,[0]])\n",
    "        if verbose == 'tensor':\n",
    "            return torch.from_numpy(out).float().cuda()\n",
    "        return out\n",
    "    def ic_v(self, x, verbose = None):\n",
    "        '''initial condition'''\n",
    "        out = np.zeros_like(x[:,[0]])\n",
    "        if verbose == 'tensor':\n",
    "            return torch.from_numpy(out).float().cuda()\n",
    "        return out"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.2、数据集生成"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Trainset_Schrodinger(object):\n",
    "    def __init__(self, problem, *args, **kwargs):\n",
    "        self.problem = problem\n",
    "        self.domain = problem.domain\n",
    "        self.args = args\n",
    "        self.method = kwargs['method']\n",
    "        \n",
    "    def __call__(self, plot=False, verbose=None):\n",
    "        if self.method == 'uniform':\n",
    "            n_x, n_t = self.args[0], self.args[1]\n",
    "            x, x_ic, x_lb, x_ub = self._uniform_sample(n_x, n_t)\n",
    "        elif self.method == 'lhs':\n",
    "            n, n_ic, n_lb, n_ub = self.args[0], self.args[1], self.args[2], self.args[3]\n",
    "            x, x_ic, x_lb, x_ub = self._lhs_sample(n, n_ic, n_lb, n_ub)\n",
    "        f_u = self.problem.f_u(x)\n",
    "        f_v = self.problem.f_v(x)\n",
    "        ic_u = self.problem.ic_u(x_ic)\n",
    "        ic_v = self.problem.ic_v(x_ic)\n",
    "        \n",
    "        if plot:\n",
    "            fig = plt.figure()\n",
    "            ax = fig.add_subplot(111)\n",
    "            ax.scatter(x[:, 0], x[:, 1], facecolor='r', s=10)\n",
    "            ax.scatter(x_ic[:, 0], x_ic[:, 1], facecolor='b', s=10)\n",
    "            ax.scatter(x_lb[:, 0], x_lb[:, 1], facecolor='g', s=10)\n",
    "            ax.scatter(x_ub[:, 0], x_ub[:, 1], facecolor='g', s=10)\n",
    "            ax.set_xlim(self.domain[0]-0.01, self.domain[1]+0.01)\n",
    "            ax.set_ylim(self.domain[2]-0.01, self.domain[3]+0.01)\n",
    "            ax.set_aspect('equal')\n",
    "            plt.show()\n",
    "            \n",
    "        if verbose is not None:\n",
    "            x = torch.from_numpy(x).float().cuda()\n",
    "            x_ic = torch.from_numpy(x_ic).float().cuda()\n",
    "            x_lb = torch.from_numpy(x_lb).float().cuda()\n",
    "            x_ub = torch.from_numpy(x_ub).float().cuda()\n",
    "            f_u = torch.from_numpy(f_u).float().cuda()\n",
    "            f_v = torch.from_numpy(f_v).float().cuda()\n",
    "            ic_u = torch.from_numpy(ic_u).float().cuda()\n",
    "            ic_v = torch.from_numpy(ic_v).float().cuda()\n",
    "            return x, x_ic, x_lb, x_ub, f_u, f_v, ic_u, ic_v\n",
    "        return x, x_ic, x_lb, x_ub, f_u, f_v, ic_u, ic_v\n",
    "        \n",
    "    def _uniform_sample(self, n_x, n_t):\n",
    "        x_min, x_max, t_min, t_max = self.domain\n",
    "        x = np.linspace(x_min, x_max, n_x)\n",
    "        t = np.linspace(t_min, t_max, n_t)\n",
    "        x, t = np.meshgrid(x, t)\n",
    "        xt = np.hstack((x.reshape(x.size, -1), t.reshape(t.size, -1)))\n",
    "        \n",
    "        mask1 =  (xt[:, 1] - t_min) == 0\n",
    "        x_ic =xt[mask1]\n",
    "        mask2 = (xt[:, 0] - x_min) == 0\n",
    "        x_lb = xt[mask2]\n",
    "        mask3 = (x_max - xt[:, 0]) == 0\n",
    "        x_ub = xt[mask3]\n",
    "        \n",
    "        x = xt[np.logical_not(mask1 + mask2 + mask3)]\n",
    "\n",
    "        return x, x_ic, x_lb, x_ub\n",
    "        \n",
    "    def _lhs_sample(self, n, n_ic, n_lb, n_ub):\n",
    "        x_min, x_max, t_min, t_max = self.domain\n",
    "\n",
    "        lb = np.array([x_min, t_min])\n",
    "        ub = np.array([x_max, t_max])\n",
    "        x = lb + (ub - lb) * lhs(2, n)\n",
    "\n",
    "        lb = np.array([x_min, t_min])\n",
    "        ub = np.array([x_max, t_min])\n",
    "        x_ic = lb + (ub - lb) * lhs(2, n_ic)\n",
    "\n",
    "        lb = np.array([x_min, t_min])\n",
    "        ub = np.array([x_min, t_max])\n",
    "        x_lb = lb + (ub - lb) * lhs(2, n_lb)\n",
    "        x_ub = x_lb.copy()\n",
    "        x_ub[:,0] += x_max - x_min\n",
    "        \n",
    "        return x, x_ic, x_lb, x_ub"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Testset_Schrodinger(object):\n",
    "    \"\"\"Dataset on a square domain\"\"\"\n",
    "    def __init__(self, problem, *args, **kwargs):\n",
    "        self.problem = problem\n",
    "        self.domain = problem.domain\n",
    "        self.args = args\n",
    "        self.method = kwargs['method']\n",
    "\n",
    "    def __repr__(self):\n",
    "        return f'{self.__doc__}'\n",
    "        \n",
    "    def __call__(self, plot=False, verbose=None):\n",
    "        if self.method == 'uniform':\n",
    "            n_x, n_t = self.args[0], self.args[1]\n",
    "            X, x, t = self._uniform_sample(n_x, n_t)\n",
    "        \n",
    "        if plot == True:\n",
    "            fig = plt.figure()\n",
    "            ax = fig.add_subplot(111)\n",
    "            ax.scatter(X[:, 0], X[:, 1], facecolor='r', s=10)\n",
    "            ax.set_xlim(self.domain[0]-0.01, self.domain[1]+0.01)\n",
    "            ax.set_ylim(self.domain[2]-0.01, self.domain[3]+0.01)\n",
    "            ax.set_aspect('equal')\n",
    "            plt.show() \n",
    "            \n",
    "        if verbose == 'tensor':\n",
    "            X = torch.from_numpy(X).float().cuda() \n",
    "        return X, x, t\n",
    "\n",
    "    def _uniform_sample(self, n_x, n_t):\n",
    "        x_min, x_max, t_min, t_max = self.domain\n",
    "        x = np.linspace(x_min, x_max, n_x)\n",
    "        t = np.linspace(t_min, t_max, n_t)\n",
    "        x, t = np.meshgrid(x, t)\n",
    "        X = np.hstack((x.reshape(x.size, -1), t.reshape(t.size, -1)))\n",
    "        return X, x, t\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.3、网络结构\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def grad(outputs, inputs):\n",
    "    return torch.autograd.grad(outputs, inputs, grad_outputs=torch.ones_like(outputs), create_graph=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "class PINN_Schrodinger(DNN):\n",
    "    '''\n",
    "    Physics Constrained Neural Networks\n",
    "    '''\n",
    "    def __init__(self, dim_in, dim_out, dim_hidden, hidden_layers, act_name = 'tanh', init_name = 'xavier_normal'):\n",
    "        super().__init__(dim_in, dim_out, dim_hidden, hidden_layers, act_name = act_name, init_name = init_name)\n",
    "        \n",
    "    def forward(self, x, x_ic = None, x_lb=None, x_ub=None):\n",
    "        x.requires_grad_(True)\n",
    "        # h = u + iv\n",
    "        uv = super().forward(x)\n",
    "        u = uv[:,0:1]\n",
    "        v = uv[:,1:2]\n",
    "\n",
    "        grad_u = grad(u, x)[0]\n",
    "        u_x = grad_u[:, [0]]\n",
    "        u_t = grad_u[:, [1]]\n",
    "        u_xx = grad(u_x, x)[0][:, [0]]\n",
    "        \n",
    "        grad_v = grad(v, x)[0]     \n",
    "        v_x = grad_v[:, [0]]\n",
    "        v_t = grad_v[:, [1]]\n",
    "        v_xx = grad(v_x, x)[0][:, [0]]\n",
    "\n",
    "        x.detach_()   \n",
    "\n",
    "        f_u = u_t + 0.5*v_xx + (u**2 + v**2)*v\n",
    "        f_v = v_t - 0.5*u_xx - (u**2 + v**2)*u  \n",
    "        \n",
    "        if x_ic is not None:\n",
    "            ic_uv = super().forward(x_ic)\n",
    "            ic_u = ic_uv[:,0:1]\n",
    "            ic_v = ic_uv[:,1:2]\n",
    "            if x_lb is not None:\n",
    "                x_lb.requires_grad_(True)\n",
    "                lb_uv = super().forward(x_lb)\n",
    "                lb_u = lb_uv[:,0:1]\n",
    "                lb_v = lb_uv[:,1:2]\n",
    "                lb_u_x = grad(lb_u, x_lb)[0][:, [0]]\n",
    "                lb_v_x = grad(lb_v, x_lb)[0][:, [0]]\n",
    "                x_lb.detach_()   \n",
    "                if x_ub is not None:\n",
    "                    x_ub.requires_grad_(True)\n",
    "                    ub_uv = super().forward(x_ub)\n",
    "                    ub_u = ub_uv[:,0:1]\n",
    "                    ub_v = ub_uv[:,1:2]\n",
    "                    ub_u_x = grad(ub_u, x_ub)[0][:, [0]]\n",
    "                    ub_v_x = grad(ub_v, x_ub)[0][:, [0]]\n",
    "                    x_ub.detach_()   \n",
    "                    return u, v, f_u, f_v, ic_u, ic_v, lb_u, lb_v, ub_u, ub_v, lb_u_x, lb_v_x, ub_u_x, ub_v_x\n",
    "                else:\n",
    "                    return u, v, f_u, f_v, ic_u, ic_v, lb_u, lb_v, lb_u_x, lb_v_x\n",
    "            else:\n",
    "                return u, v, f_u, f_v, ic_u, ic_v\n",
    "        elif x_lb is not None:\n",
    "            x_lb.requires_grad_(True)\n",
    "            lb_uv = super().forward(x_lb)\n",
    "            lb_u = lb_uv[:,0:1]\n",
    "            lb_v = lb_uv[:,1:2]\n",
    "            lb_u_x = grad(lb_u, x_lb)[0][:, [0]]\n",
    "            lb_v_x = grad(lb_v, x_lb)[0][:, [0]]\n",
    "            x_lb.detach_()   \n",
    "            if x_ub is not None:\n",
    "                x_ub.requires_grad_(True)\n",
    "                ub_uv = super().forward(x_ub)\n",
    "                ub_u = ub_uv[:,0:1]\n",
    "                ub_v = ub_uv[:,1:2]\n",
    "                ub_u_x = grad(ub_u, x_ub)[0][:, [0]]\n",
    "                ub_v_x = grad(ub_v, x_ub)[0][:, [0]]\n",
    "                x_ub.detach_()   \n",
    "                return u, v, f_u, f_v, lb_u, lb_v, ub_u, ub_v, lb_u_x, lb_v_x, ub_u_x, ub_v_x\n",
    "            else:\n",
    "                return u, v, f_u, f_v, lb_u, lb_v, lb_u_x, lb_v_x\n",
    "        elif x_ub is not None:\n",
    "            x_ub.requires_grad_(True)\n",
    "            ub_uv = super().forward(x_ub)\n",
    "            ub_u = ub_uv[:,0:1]\n",
    "            ub_v = ub_uv[:,1:2]\n",
    "            ub_u_x = grad(ub_u, x_ub)[0][:, [0]]\n",
    "            ub_v_x = grad(ub_v, x_ub)[0][:, [0]]\n",
    "            x_ub.detach_()   \n",
    "            return u, v, f_u, f_v, ub_u, ub_v, ub_u_x, ub_v_x\n",
    "        return u, v, f_u, f_v"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ResPINN_Schrodinger(ResDNN):\n",
    "    '''\n",
    "    Physics Constrained Neural Networks\n",
    "    '''\n",
    "    def __init__(self, dim_in, dim_out, dim_hidden, res_blocks, act_name = 'tanh', init_name = 'xavier_normal'):\n",
    "        super().__init__(dim_in, dim_out, dim_hidden, res_blocks, act_name = act_name, init_name = init_name)\n",
    "        \n",
    "    def forward(self, x, x_ic = None, x_lb=None, x_ub=None):\n",
    "        x.requires_grad_(True)\n",
    "        # h = u + iv\n",
    "        uv = super().forward(x)\n",
    "        u = uv[:,0:1]\n",
    "        v = uv[:,1:2]\n",
    "\n",
    "        grad_u = grad(u, x)[0]\n",
    "        u_x = grad_u[:, [0]]\n",
    "        u_t = grad_u[:, [1]]\n",
    "        u_xx = grad(u_x, x)[0][:, [0]]\n",
    "        \n",
    "        grad_v = grad(v, x)[0]     \n",
    "        v_x = grad_v[:, [0]]\n",
    "        v_t = grad_v[:, [1]]\n",
    "        v_xx = grad(v_x, x)[0][:, [0]]\n",
    "\n",
    "        x.detach_()   \n",
    "\n",
    "        f_u = u_t + 0.5*v_xx + (u**2 + v**2)*v\n",
    "        f_v = v_t - 0.5*u_xx - (u**2 + v**2)*u  \n",
    "        \n",
    "        if x_ic is not None:\n",
    "            ic_uv = super().forward(x_ic)\n",
    "            ic_u = ic_uv[:,0:1]\n",
    "            ic_v = ic_uv[:,1:2]\n",
    "            if x_lb is not None:\n",
    "                x_lb.requires_grad_(True)\n",
    "                lb_uv = super().forward(x_lb)\n",
    "                lb_u = lb_uv[:,0:1]\n",
    "                lb_v = lb_uv[:,1:2]\n",
    "                lb_u_x = grad(lb_u, x_lb)[0][:, [0]]\n",
    "                lb_v_x = grad(lb_v, x_lb)[0][:, [0]]\n",
    "                x_lb.detach_()   \n",
    "                if x_ub is not None:\n",
    "                    x_ub.requires_grad_(True)\n",
    "                    ub_uv = super().forward(x_ub)\n",
    "                    ub_u = ub_uv[:,0:1]\n",
    "                    ub_v = ub_uv[:,1:2]\n",
    "                    ub_u_x = grad(ub_u, x_ub)[0][:, [0]]\n",
    "                    ub_v_x = grad(ub_v, x_ub)[0][:, [0]]\n",
    "                    x_ub.detach_()   \n",
    "                    return u, v, f_u, f_v, ic_u, ic_v, lb_u, lb_v, ub_u, ub_v, lb_u_x, lb_v_x, ub_u_x, ub_v_x\n",
    "                else:\n",
    "                    return u, v, f_u, f_v, ic_u, ic_v, lb_u, lb_v, lb_u_x, lb_v_x\n",
    "            else:\n",
    "                return u, v, f_u, f_v, ic_u, ic_v\n",
    "        elif x_lb is not None:\n",
    "            x_lb.requires_grad_(True)\n",
    "            lb_uv = super().forward(x_lb)\n",
    "            lb_u = lb_uv[:,0:1]\n",
    "            lb_v = lb_uv[:,1:2]\n",
    "            lb_u_x = grad(lb_u, x_lb)[0][:, [0]]\n",
    "            lb_v_x = grad(lb_v, x_lb)[0][:, [0]]\n",
    "            x_lb.detach_()   \n",
    "            if x_ub is not None:\n",
    "                x_ub.requires_grad_(True)\n",
    "                ub_uv = super().forward(x_ub)\n",
    "                ub_u = ub_uv[:,0:1]\n",
    "                ub_v = ub_uv[:,1:2]\n",
    "                ub_u_x = grad(ub_u, x_ub)[0][:, [0]]\n",
    "                ub_v_x = grad(ub_v, x_ub)[0][:, [0]]\n",
    "                x_ub.detach_()   \n",
    "                return u, v, f_u, f_v, lb_u, lb_v, ub_u, ub_v, lb_u_x, lb_v_x, ub_u_x, ub_v_x\n",
    "            else:\n",
    "                return u, v, f_u, f_v, lb_u, lb_v, lb_u_x, lb_v_x\n",
    "        elif x_ub is not None:\n",
    "            x_ub.requires_grad_(True)\n",
    "            ub_uv = super().forward(x_ub)\n",
    "            ub_u = ub_uv[:,0:1]\n",
    "            ub_v = ub_uv[:,1:2]\n",
    "            ub_u_x = grad(ub_u, x_ub)[0][:, [0]]\n",
    "            ub_v_x = grad(ub_v, x_ub)[0][:, [0]]\n",
    "            x_ub.detach_()   \n",
    "            return u, v, f_u, f_v, ub_u, ub_v, ub_u_x, ub_v_x\n",
    "        return u, v, f_u, f_v"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.4、Options"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Options_Schrodinger(object):\n",
    "    def __init__(self):\n",
    "        parser = argparse.ArgumentParser()\n",
    "        parser.add_argument('--no_cuda', action='store_true', default=False, help='disable CUDA or not')\n",
    "        parser.add_argument('--dim_hidden', type=int, default=20, help='neurons in hidden layers')\n",
    "        parser.add_argument('--hidden_layers', type=int, default=6, help='number of hidden layers')\n",
    "        parser.add_argument('--res_blocks', type=int, default=4, help='number of residual blocks')\n",
    "        parser.add_argument('--dropout', type=float, default=0.5, help='dropout rate')\n",
    "        parser.add_argument('--lam1', type=float, default=1, help='weight in loss function')\n",
    "        parser.add_argument('--lam2', type=float, default=1, help='weight in loss function')\n",
    "        parser.add_argument('--lr', type=float, default=1e-3, help='initial learning rate')\n",
    "        parser.add_argument('--epochs_Adam', type=int, default=2500, help='epochs for Adam optimizer')\n",
    "        parser.add_argument('--epochs_LBFGS', type=int, default=500, help='epochs for LBFGS optimizer')\n",
    "        parser.add_argument('--step_size', type=int, default=2000, help='step size in lr_scheduler for Adam optimizer')\n",
    "        parser.add_argument('--gamma', type=float, default=0.7, help='gamma in lr_scheduler for Adam optimizer')\n",
    "        parser.add_argument('--resume', type=bool, default=False, help='resume or not')\n",
    "        parser.add_argument('--sample_method', type=str, default='uniform', help='sample method')\n",
    "        parser.add_argument('--n_x', type=int, default=256, help='sample points in x-direction for uniform sample')\n",
    "        parser.add_argument('--n_t', type=int, default=201, help='sample points in t-direction for uniform sample')\n",
    "        parser.add_argument('--n', type=int, default=20000, help='sample points in domain for lhs sample')\n",
    "        parser.add_argument('--n_ic', type=int, default=400, help='sample points at t = 0 for lhs sample')\n",
    "        parser.add_argument('--n_lb', type=int, default=400, help='sample points on the boundary for lhs sample')\n",
    "        parser.add_argument('--n_ub', type=int, default=400, help='sample points on the boundary for lhs sample')\n",
    "        parser.add_argument('--case', type=int, default=1, help='problem case')\n",
    "        self.parser = parser\n",
    "        \n",
    "    def parse(self):\n",
    "        arg = self.parser.parse_args(args=[])\n",
    "        arg.cuda = not arg.no_cuda and torch.cuda.is_available()\n",
    "        arg.device = torch.device('cuda' if not arg.no_cuda and torch.cuda.is_available() else 'cpu')\n",
    "        return arg"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.5、训练过程"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Parameters of the neural networks can be learned by minimizing the mean squared error loss\n",
    "\n",
    "$$MSE = MSE_f+MSE_0+MSE_b$$\n",
    "\n",
    "where\n",
    "\n",
    "$$MSE_f = \\frac{1}{N_f}\\sum_{i=1}^{N_f}|f(t_f^i,x_f^i)|^2,\\quad MSE_0 = \\frac{1}{N_0}\\sum_{i=1}^{N_0}|h(0,x_0^i)-h_0^i|^2$$\n",
    "\n",
    "$$MSE_b = \\frac{1}{N_b}\\sum_{i=1}^{N_b}(|h^i(t_b^i,-5)-h^i(t_b^i,5)|^2+|h_x^i(t_b^i,-5)-h_x^i(t_b^i,5)|^2)$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "def save_model_Schrodinger(state, is_best=None, save_dir=None):\n",
    "    last_model = os.path.join(save_dir, 'last_model_Schrodinger.pth.tar')\n",
    "    torch.save(state, last_model)\n",
    "    if is_best:\n",
    "        best_model = os.path.join(save_dir, 'best_model_Schrodinger.pth.tar')\n",
    "        shutil.copyfile(last_model, best_model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Trainer_Schrodinger(object):\n",
    "    def __init__(self, args):\n",
    "        self.device  = args.device\n",
    "        self.problem = args.problem\n",
    "        \n",
    "        print(f'Working device: {self.device}')\n",
    "        \n",
    "        self.lam1 = args.lam1\n",
    "        self.lam2 = args.lam2\n",
    "        self.criterion = nn.MSELoss()\n",
    "        \n",
    "        self.model = args.model\n",
    "        self.model_name = self.model.__class__.__name__\n",
    "        self.model_path = self._model_path()\n",
    "                \n",
    "        self.epochs_Adam = args.epochs_Adam\n",
    "        self.epochs_LBFGS = args.epochs_LBFGS\n",
    "        self.optimizer_Adam = optim.Adam(self.model.parameters(), lr=args.lr)\n",
    "        self.optimizer_LBFGS = optim.LBFGS(self.model.parameters(), max_iter=20, tolerance_grad=1.e-8, tolerance_change=1.e-12)\n",
    "        self.lr_scheduler = StepLR(self.optimizer_Adam, step_size=args.step_size, gamma=args.gamma)\n",
    "\n",
    "        self.model.to(self.device)\n",
    "        self.model.zero_grad()\n",
    "        \n",
    "        self.x,     self.x_ic,     self.x_lb,     self.x_ub,     self.f_u,     \\\n",
    "        self.f_v,     self.ic_u,     self.ic_v   = args.trainset(verbose='tensor')\n",
    "        \n",
    "        self.x_val, self.x_ic_val, self.x_lb_val, self.x_ub_val, self.f_u_val, \\\n",
    "        self.f_v_val, self.ic_u_val, self.ic_v_val = args.validset(verbose='tensor')\n",
    "        \n",
    "        if self.device == torch.device(type='cuda'):\n",
    "            for item in [self.x,     self.x_ic,     self.x_lb,     self.x_ub,     self.f_u,     self.f_v,     self.ic_u,     self.ic_v    ]:\n",
    "                item = item.to(self.device)\n",
    "            for item in [self.x_val, self.x_ic_val, self.x_lb_val, self.x_ub_val, self.f_u_val, self.f_v_val, self.ic_u_val, self.ic_v_val]:\n",
    "                item = item.to(self.device)\n",
    "                \n",
    "        ic_bc_points = np.vstack([self.x_ic.clone().detach().cpu(), self.x_lb.clone().detach().cpu(), self.x_ub.clone().detach().cpu()])\n",
    "        np.save('ic_bc_points_Schrodinger.npy',ic_bc_points)\n",
    "        \n",
    "    def _model_path(self):\n",
    "        \"\"\"Path to save the model\"\"\"\n",
    "        if not os.path.exists('checkpoints'):\n",
    "            os.mkdir('checkpoints')\n",
    "\n",
    "        path = os.path.join('checkpoints', self.model_name)\n",
    "        if not os.path.exists(path):\n",
    "            os.mkdir(path)\n",
    "    \n",
    "        return path\n",
    "            \n",
    "    def train_Adam(self):\n",
    "        self.optimizer_Adam.zero_grad()\n",
    "\n",
    "        _, _, f_u_pred, f_v_pred, ic_u_pred, ic_v_pred, lb_u_pred, lb_v_pred, \\\n",
    "        ub_u_pred, ub_v_pred, lb_u_x_pred, lb_v_x_pred, ub_u_x_pred, ub_v_x_pred = self.model(self.x, self.x_ic, self.x_lb, self.x_ub)\n",
    "        \n",
    "        loss1 = self.criterion(ic_u_pred, self.ic_u) + self.criterion(ic_v_pred, self.ic_v)\n",
    "        loss2 = self.criterion(lb_u_pred, ub_u_pred) + self.criterion(lb_v_pred, ub_v_pred) + \\\n",
    "        self.criterion(lb_u_x_pred, ub_u_x_pred) + self.criterion(lb_v_x_pred, ub_v_x_pred)\n",
    "        loss3 = self.criterion(f_u_pred, self.f_u) + self.criterion(f_v_pred, self.f_v)\n",
    "        loss = loss1 + self.lam1 * loss2 + self.lam2 * loss3\n",
    "\n",
    "        loss.backward()\n",
    "        self.optimizer_Adam.step()\n",
    "        self.lr_scheduler.step()\n",
    "\n",
    "        return loss.item(), loss1.item(), loss2.item(), loss3.item()\n",
    "\n",
    "    def infos_Adam(self, epoch, loss, loss1, loss2, loss3):\n",
    "        infos = 'Adam  ' + \\\n",
    "            f'Epoch #{epoch:5d}/{self.epochs_Adam+self.epochs_LBFGS} ' + \\\n",
    "            f'Loss: {loss:.4e} = {loss1:.4e} + {self.lam1} * {loss2:.4e} + {self.lam2} * {loss3:.4e} ' + \\\n",
    "            f'lr: {self.lr_scheduler.get_lr()[0]:.2e} '\n",
    "        print(infos)\n",
    "        \n",
    "    def train_LBFGS(self):\n",
    "\n",
    "        # only used to compute loss_int and loss_bc1 for monitoring\n",
    "        _, _, f_u_pred, f_v_pred, ic_u_pred, ic_v_pred, lb_u_pred, lb_v_pred, \\\n",
    "        ub_u_pred, ub_v_pred, lb_u_x_pred, lb_v_x_pred, ub_u_x_pred, ub_v_x_pred = self.model(self.x, self.x_ic, self.x_lb, self.x_ub)\n",
    "        \n",
    "        loss1 = self.criterion(ic_u_pred, self.ic_u) + self.criterion(ic_v_pred, self.ic_v)\n",
    "        loss2 = self.criterion(lb_u_pred, ub_u_pred) + self.criterion(lb_v_pred, ub_v_pred) + \\\n",
    "        self.criterion(lb_u_x_pred, ub_u_x_pred) + self.criterion(lb_v_x_pred, ub_v_x_pred)\n",
    "        loss3 = self.criterion(f_u_pred, self.f_u) + self.criterion(f_v_pred, self.f_v)\n",
    "        \n",
    "        def closure():\n",
    "            if torch.is_grad_enabled():\n",
    "                self.optimizer_LBFGS.zero_grad()\n",
    "                _, _, f_u_pred, f_v_pred, ic_u_pred, ic_v_pred, lb_u_pred, lb_v_pred, \\\n",
    "                ub_u_pred, ub_v_pred, lb_u_x_pred, lb_v_x_pred, ub_u_x_pred, ub_v_x_pred = self.model(self.x, self.x_ic, self.x_lb, self.x_ub)\n",
    "\n",
    "                loss1 = self.criterion(ic_u_pred, self.ic_u) + self.criterion(ic_v_pred, self.ic_v)\n",
    "                loss2 = self.criterion(lb_u_pred, ub_u_pred) + self.criterion(lb_v_pred, ub_v_pred) + \\\n",
    "                self.criterion(lb_u_x_pred, ub_u_x_pred) + self.criterion(lb_v_x_pred, ub_v_x_pred)\n",
    "                loss3 = self.criterion(f_u_pred, self.f_u) + self.criterion(f_v_pred, self.f_v)\n",
    "                loss = loss1 + self.lam1 * loss2 + self.lam2 * loss3\n",
    "            if loss.requires_grad:\n",
    "                loss.backward()\n",
    "            return loss\n",
    "\n",
    "        self.optimizer_LBFGS.step(closure)\n",
    "        loss = closure()\n",
    "\n",
    "        return loss.item(), loss1.item(), loss2.item(), loss3.item()\n",
    "        \n",
    "    def infos_LBFGS(self, epoch, loss, loss1, loss2, loss3):\n",
    "        infos = 'LBFGS ' + \\\n",
    "            f'Epoch #{epoch:5d}/{self.epochs_Adam+self.epochs_LBFGS} ' + \\\n",
    "            f'Loss: {loss:.4e} = {loss1:.4e} + {self.lam1} * {loss2:.4e} + {self.lam2} * {loss3:.4e} '\n",
    "        print(infos)\n",
    "\n",
    "    def validate(self, epoch):\n",
    "        self.model.eval()\n",
    "        _, _, f_u_pred, f_v_pred, ic_u_pred, ic_v_pred, lb_u_pred, lb_v_pred, \\\n",
    "        ub_u_pred, ub_v_pred, lb_u_x_pred, lb_v_x_pred, ub_u_x_pred, ub_v_x_pred = self.model(self.x_val, self.x_ic_val, self.x_lb_val, self.x_ub_val)\n",
    "        \n",
    "        loss1 = self.criterion(ic_u_pred, self.ic_u_val) + self.criterion(ic_v_pred, self.ic_v_val)\n",
    "        loss2 = self.criterion(lb_u_pred, ub_u_pred) + self.criterion(lb_v_pred, ub_v_pred) + \\\n",
    "        self.criterion(lb_u_x_pred, ub_u_x_pred) + self.criterion(lb_v_x_pred, ub_v_x_pred)\n",
    "        loss3 = self.criterion(f_u_pred, self.f_u_val) + self.criterion(f_v_pred, self.f_v_val)\n",
    "        loss = loss1 + self.lam1 * loss2 + self.lam2 * loss3\n",
    "        \n",
    "        infos = 'Valid ' + \\\n",
    "            f'Epoch #{epoch+1:5d}/{self.epochs_Adam+self.epochs_LBFGS} ' + \\\n",
    "            f'Loss: {loss:.4e} '\n",
    "        print(infos)\n",
    "        self.model.train()\n",
    "        return loss.item()\n",
    "    \n",
    "    def train(self):\n",
    "        best_loss = 1.e10\n",
    "        train_losses_index = []\n",
    "        train_losses = []\n",
    "        valid_losses_index = []\n",
    "        valid_losses = []\n",
    "        \n",
    "        for epoch in range(self.epochs_Adam):\n",
    "            loss, loss1, loss2, loss3 = self.train_Adam()\n",
    "            train_losses_index += [epoch]\n",
    "            train_losses += [loss]\n",
    "            \n",
    "            if (epoch + 1) % 100 == 0:\n",
    "                self.infos_Adam(epoch+1, loss, loss1, loss2, loss3)\n",
    "                \n",
    "                valid_loss = self.validate(epoch)\n",
    "                is_best = valid_loss < best_loss\n",
    "                best_loss = valid_loss if is_best else best_loss                \n",
    "                state = {\n",
    "                    'epoch': epoch,\n",
    "                    'state_dict': self.model.state_dict(),\n",
    "                    'best_loss': best_loss\n",
    "                }\n",
    "                save_model_Schrodinger(state, is_best, save_dir=self.model_path)\n",
    "                valid_losses_index += [epoch]\n",
    "                valid_losses += [valid_loss]\n",
    "            \n",
    "        for epoch in range(self.epochs_Adam, self.epochs_Adam + self.epochs_LBFGS):\n",
    "            loss, loss1, loss2, loss3 = self.train_LBFGS()\n",
    "            train_losses_index += [epoch]\n",
    "            train_losses += [loss]\n",
    "            \n",
    "            if (epoch + 1) % 20 == 0:\n",
    "                self.infos_LBFGS(epoch+1, loss, loss1, loss2, loss3)\n",
    "                \n",
    "                valid_loss = self.validate(epoch)\n",
    "                is_best = valid_loss < best_loss\n",
    "                best_loss = valid_loss if is_best else best_loss                \n",
    "                state = {\n",
    "                    'epoch': epoch,\n",
    "                    'state_dict': self.model.state_dict(),\n",
    "                    'best_loss': best_loss\n",
    "                }\n",
    "                save_model_Schrodinger(state, is_best, save_dir=self.model_path)\n",
    "                valid_losses_index += [epoch]\n",
    "                valid_losses += [valid_loss]\n",
    "                \n",
    "        # save loss curve info\n",
    "        np.save('Schrodinger_loss.npy',[train_losses_index,train_losses,valid_losses_index,valid_losses])\n",
    "        \n",
    "        # loss curve\n",
    "        fig = plt.figure(figsize=(10,5))\n",
    "        ax = fig.add_subplot(111)\n",
    "        ax.set_title('Loss curve',usetex = True,fontsize=20)\n",
    "        ax.set_yscale(\"log\")\n",
    "        ax.set_xlabel('epoch',usetex = True,fontsize=20)\n",
    "        ax.set_ylabel('loss',usetex = True,fontsize=20)\n",
    "        ax.plot(train_losses_index, train_losses, color = 'g', label = 'train loss')\n",
    "        ax.plot(valid_losses_index, valid_losses, color = 'r', linestyle='--', label = 'valid loss')\n",
    "        ax.legend(frameon=False, loc = 'best')\n",
    "        plt.savefig('Schrodinger_loss')\n",
    "        plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Working device: cuda\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "d:\\program files (x86)\\python\\lib\\site-packages\\torch\\optim\\lr_scheduler.py:351: UserWarning: To get the last learning rate computed by the scheduler, please use `get_last_lr()`.\n",
      "  \"please use `get_last_lr()`.\", UserWarning)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Adam  Epoch #  100/3000 Loss: 1.0302e-01 = 5.8839e-02 + 1 * 1.0567e-03 + 1 * 4.3122e-02 lr: 1.00e-03 \n",
      "Valid Epoch #  100/3000 Loss: 1.0234e-01 \n",
      "Adam  Epoch #  200/3000 Loss: 6.8165e-02 = 3.7395e-02 + 1 * 3.8061e-04 + 1 * 3.0389e-02 lr: 1.00e-03 \n",
      "Valid Epoch #  200/3000 Loss: 6.8046e-02 \n",
      "Adam  Epoch #  300/3000 Loss: 6.1924e-02 = 3.2961e-02 + 1 * 2.6601e-04 + 1 * 2.8697e-02 lr: 1.00e-03 \n",
      "Valid Epoch #  300/3000 Loss: 6.1884e-02 \n",
      "Adam  Epoch #  400/3000 Loss: 5.8516e-02 = 3.0903e-02 + 1 * 2.0911e-04 + 1 * 2.7404e-02 lr: 1.00e-03 \n",
      "Valid Epoch #  400/3000 Loss: 5.8487e-02 \n",
      "Adam  Epoch #  500/3000 Loss: 5.5823e-02 = 2.9044e-02 + 1 * 1.7117e-04 + 1 * 2.6608e-02 lr: 1.00e-03 \n",
      "Valid Epoch #  500/3000 Loss: 5.5798e-02 \n",
      "Adam  Epoch #  600/3000 Loss: 5.3428e-02 = 2.7420e-02 + 1 * 1.4690e-04 + 1 * 2.5861e-02 lr: 1.00e-03 \n",
      "Valid Epoch #  600/3000 Loss: 5.3405e-02 \n",
      "Adam  Epoch #  700/3000 Loss: 5.1220e-02 = 2.6096e-02 + 1 * 1.2792e-04 + 1 * 2.4995e-02 lr: 1.00e-03 \n",
      "Valid Epoch #  700/3000 Loss: 5.1198e-02 \n",
      "Adam  Epoch #  800/3000 Loss: 4.9189e-02 = 2.5064e-02 + 1 * 1.0831e-04 + 1 * 2.4016e-02 lr: 1.00e-03 \n",
      "Valid Epoch #  800/3000 Loss: 4.9170e-02 \n",
      "Adam  Epoch #  900/3000 Loss: 4.7313e-02 = 2.4229e-02 + 1 * 8.8143e-05 + 1 * 2.2996e-02 lr: 1.00e-03 \n",
      "Valid Epoch #  900/3000 Loss: 4.7295e-02 \n",
      "Adam  Epoch # 1000/3000 Loss: 4.5542e-02 = 2.3464e-02 + 1 * 7.0380e-05 + 1 * 2.2007e-02 lr: 1.00e-03 \n",
      "Valid Epoch # 1000/3000 Loss: 4.5524e-02 \n",
      "Adam  Epoch # 1100/3000 Loss: 4.3846e-02 = 2.2696e-02 + 1 * 5.6212e-05 + 1 * 2.1094e-02 lr: 1.00e-03 \n",
      "Valid Epoch # 1100/3000 Loss: 4.3830e-02 \n",
      "Adam  Epoch # 1200/3000 Loss: 4.2265e-02 = 2.1944e-02 + 1 * 4.5308e-05 + 1 * 2.0275e-02 lr: 1.00e-03 \n",
      "Valid Epoch # 1200/3000 Loss: 4.2250e-02 \n",
      "Adam  Epoch # 1300/3000 Loss: 4.0837e-02 = 2.1244e-02 + 1 * 3.6374e-05 + 1 * 1.9556e-02 lr: 1.00e-03 \n",
      "Valid Epoch # 1300/3000 Loss: 4.0823e-02 \n",
      "Adam  Epoch # 1400/3000 Loss: 3.9519e-02 = 2.0569e-02 + 1 * 2.8046e-05 + 1 * 1.8921e-02 lr: 1.00e-03 \n",
      "Valid Epoch # 1400/3000 Loss: 3.9506e-02 \n",
      "Adam  Epoch # 1500/3000 Loss: 3.8277e-02 = 1.9889e-02 + 1 * 2.0943e-05 + 1 * 1.8367e-02 lr: 1.00e-03 \n",
      "Valid Epoch # 1500/3000 Loss: 3.8265e-02 \n",
      "Adam  Epoch # 1600/3000 Loss: 3.7095e-02 = 1.9195e-02 + 1 * 1.5676e-05 + 1 * 1.7885e-02 lr: 1.00e-03 \n",
      "Valid Epoch # 1600/3000 Loss: 3.7084e-02 \n",
      "Adam  Epoch # 1700/3000 Loss: 3.5955e-02 = 1.8496e-02 + 1 * 1.2149e-05 + 1 * 1.7447e-02 lr: 1.00e-03 \n",
      "Valid Epoch # 1700/3000 Loss: 3.5944e-02 \n",
      "Adam  Epoch # 1800/3000 Loss: 3.4851e-02 = 1.7814e-02 + 1 * 1.0253e-05 + 1 * 1.7027e-02 lr: 1.00e-03 \n",
      "Valid Epoch # 1800/3000 Loss: 3.4840e-02 \n",
      "Adam  Epoch # 1900/3000 Loss: 3.3790e-02 = 1.7170e-02 + 1 * 9.8716e-06 + 1 * 1.6610e-02 lr: 1.00e-03 \n",
      "Valid Epoch # 1900/3000 Loss: 3.3780e-02 \n",
      "Adam  Epoch # 2000/3000 Loss: 3.2879e-02 = 1.6458e-02 + 1 * 1.1266e-05 + 1 * 1.6409e-02 lr: 4.90e-04 \n",
      "Valid Epoch # 2000/3000 Loss: 3.2867e-02 \n",
      "Adam  Epoch # 2100/3000 Loss: 3.2202e-02 = 1.6244e-02 + 1 * 1.1832e-05 + 1 * 1.5946e-02 lr: 7.00e-04 \n",
      "Valid Epoch # 2100/3000 Loss: 3.2196e-02 \n",
      "Adam  Epoch # 2200/3000 Loss: 3.1548e-02 = 1.5860e-02 + 1 * 1.3254e-05 + 1 * 1.5675e-02 lr: 7.00e-04 \n",
      "Valid Epoch # 2200/3000 Loss: 3.1542e-02 \n",
      "Adam  Epoch # 2300/3000 Loss: 3.0873e-02 = 1.5463e-02 + 1 * 1.4865e-05 + 1 * 1.5395e-02 lr: 7.00e-04 \n",
      "Valid Epoch # 2300/3000 Loss: 3.0866e-02 \n",
      "Adam  Epoch # 2400/3000 Loss: 3.1521e-02 = 1.6059e-02 + 1 * 1.9932e-05 + 1 * 1.5442e-02 lr: 7.00e-04 \n",
      "Valid Epoch # 2400/3000 Loss: 3.0184e-02 \n",
      "Adam  Epoch # 2500/3000 Loss: 2.9507e-02 = 1.4659e-02 + 1 * 1.7650e-05 + 1 * 1.4831e-02 lr: 7.00e-04 \n",
      "Valid Epoch # 2500/3000 Loss: 2.9500e-02 \n",
      "LBFGS Epoch # 2520/3000 Loss: 1.1081e-02 = 4.6928e-03 + 1 * 4.5745e-05 + 1 * 6.5896e-03 \n",
      "Valid Epoch # 2520/3000 Loss: 1.1081e-02 \n",
      "LBFGS Epoch # 2540/3000 Loss: 5.3532e-03 = 1.5446e-03 + 1 * 2.1298e-05 + 1 * 3.9130e-03 \n",
      "Valid Epoch # 2540/3000 Loss: 5.3532e-03 \n",
      "LBFGS Epoch # 2560/3000 Loss: 2.9191e-03 = 7.6253e-04 + 1 * 1.7691e-05 + 1 * 2.2385e-03 \n",
      "Valid Epoch # 2560/3000 Loss: 2.9191e-03 \n",
      "LBFGS Epoch # 2580/3000 Loss: 1.8223e-03 = 4.0435e-04 + 1 * 1.1650e-05 + 1 * 1.4570e-03 \n",
      "Valid Epoch # 2580/3000 Loss: 1.8223e-03 \n",
      "LBFGS Epoch # 2600/3000 Loss: 1.0781e-03 = 1.7729e-04 + 1 * 6.2357e-06 + 1 * 9.1845e-04 \n",
      "Valid Epoch # 2600/3000 Loss: 1.0781e-03 \n",
      "LBFGS Epoch # 2620/3000 Loss: 7.2634e-04 = 1.0768e-04 + 1 * 3.1480e-06 + 1 * 6.3216e-04 \n",
      "Valid Epoch # 2620/3000 Loss: 7.2634e-04 \n",
      "LBFGS Epoch # 2640/3000 Loss: 5.4033e-04 = 8.7639e-05 + 1 * 2.1654e-06 + 1 * 4.5553e-04 \n",
      "Valid Epoch # 2640/3000 Loss: 5.4033e-04 \n",
      "LBFGS Epoch # 2660/3000 Loss: 4.4596e-04 = 6.0832e-05 + 1 * 4.3200e-06 + 1 * 3.8494e-04 \n",
      "Valid Epoch # 2660/3000 Loss: 4.4596e-04 \n",
      "LBFGS Epoch # 2680/3000 Loss: 3.6806e-04 = 5.2153e-05 + 1 * 3.2521e-06 + 1 * 3.1518e-04 \n",
      "Valid Epoch # 2680/3000 Loss: 3.6806e-04 \n",
      "LBFGS Epoch # 2700/3000 Loss: 3.1173e-04 = 3.9566e-05 + 1 * 2.8756e-06 + 1 * 2.7185e-04 \n",
      "Valid Epoch # 2700/3000 Loss: 3.1173e-04 \n",
      "LBFGS Epoch # 2720/3000 Loss: 2.4679e-04 = 3.1654e-05 + 1 * 1.9251e-06 + 1 * 2.1707e-04 \n",
      "Valid Epoch # 2720/3000 Loss: 2.4679e-04 \n",
      "LBFGS Epoch # 2740/3000 Loss: 2.0413e-04 = 2.4886e-05 + 1 * 7.2053e-07 + 1 * 1.7997e-04 \n",
      "Valid Epoch # 2740/3000 Loss: 2.0413e-04 \n",
      "LBFGS Epoch # 2760/3000 Loss: 1.7350e-04 = 1.7694e-05 + 1 * 9.7522e-07 + 1 * 1.5573e-04 \n",
      "Valid Epoch # 2760/3000 Loss: 1.7350e-04 \n",
      "LBFGS Epoch # 2780/3000 Loss: 1.5185e-04 = 1.8100e-05 + 1 * 1.4288e-06 + 1 * 1.3326e-04 \n",
      "Valid Epoch # 2780/3000 Loss: 1.5185e-04 \n",
      "LBFGS Epoch # 2800/3000 Loss: 1.3710e-04 = 1.3976e-05 + 1 * 1.6678e-06 + 1 * 1.2195e-04 \n",
      "Valid Epoch # 2800/3000 Loss: 1.3710e-04 \n",
      "LBFGS Epoch # 2820/3000 Loss: 1.2199e-04 = 1.3245e-05 + 1 * 1.3685e-06 + 1 * 1.0797e-04 \n",
      "Valid Epoch # 2820/3000 Loss: 1.2199e-04 \n",
      "LBFGS Epoch # 2840/3000 Loss: 1.0889e-04 = 1.2100e-05 + 1 * 1.0150e-06 + 1 * 9.6170e-05 \n",
      "Valid Epoch # 2840/3000 Loss: 1.0889e-04 \n",
      "LBFGS Epoch # 2860/3000 Loss: 9.7215e-05 = 9.5592e-06 + 1 * 6.1725e-07 + 1 * 8.7397e-05 \n",
      "Valid Epoch # 2860/3000 Loss: 9.7215e-05 \n",
      "LBFGS Epoch # 2880/3000 Loss: 8.8475e-05 = 9.1043e-06 + 1 * 6.3170e-07 + 1 * 7.9143e-05 \n",
      "Valid Epoch # 2880/3000 Loss: 8.8475e-05 \n",
      "LBFGS Epoch # 2900/3000 Loss: 7.9569e-05 = 7.3698e-06 + 1 * 5.1672e-07 + 1 * 7.2259e-05 \n",
      "Valid Epoch # 2900/3000 Loss: 7.9569e-05 \n",
      "LBFGS Epoch # 2920/3000 Loss: 7.2695e-05 = 6.8024e-06 + 1 * 2.5327e-07 + 1 * 6.5994e-05 \n",
      "Valid Epoch # 2920/3000 Loss: 7.2695e-05 \n",
      "LBFGS Epoch # 2940/3000 Loss: 6.7547e-05 = 5.6349e-06 + 1 * 3.5928e-07 + 1 * 6.1665e-05 \n",
      "Valid Epoch # 2940/3000 Loss: 6.7547e-05 \n",
      "LBFGS Epoch # 2960/3000 Loss: 6.3264e-05 = 5.0165e-06 + 1 * 4.1003e-07 + 1 * 5.8172e-05 \n",
      "Valid Epoch # 2960/3000 Loss: 6.3264e-05 \n",
      "LBFGS Epoch # 2980/3000 Loss: 5.8728e-05 = 5.0004e-06 + 1 * 5.0214e-07 + 1 * 5.3413e-05 \n",
      "Valid Epoch # 2980/3000 Loss: 5.8728e-05 \n",
      "LBFGS Epoch # 3000/3000 Loss: 5.4256e-05 = 4.8769e-06 + 1 * 6.0810e-07 + 1 * 4.8934e-05 \n",
      "Valid Epoch # 3000/3000 Loss: 5.4256e-05 \n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 720x360 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 使用Trainer_Schrodinger进行训练\n",
    "args = Options_Schrodinger().parse()\n",
    "args.problem = Problem_Schrodinger()\n",
    "\n",
    "#args.model = PINN_Schrodinger(2, 2, dim_hidden=args.dim_hidden, hidden_layers=args.hidden_layers)\n",
    "args.model = ResPINN_Schrodinger(2, 2, dim_hidden=args.dim_hidden, res_blocks=args.res_blocks)\n",
    "if args.sample_method == 'uniform':\n",
    "    args.trainset = Trainset_Schrodinger(args.problem, args.n_x, args.n_t, method='uniform')\n",
    "elif args.sample_method == 'lhs':\n",
    "    args.trainset = Trainset_Schrodinger(args.problem, args.n, args.n_ic, args.n_lb, args.n_ub, method='lhs')\n",
    "args.validset = Trainset_Schrodinger(args.problem, 100, 100, method='uniform')\n",
    "    \n",
    "trainer = Trainer_Schrodinger(args)\n",
    "trainer.train()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.6、测试过程"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Tester_Schrodinger(object):\n",
    "    def __init__(self, args):\n",
    "        self.device  = args.device\n",
    "\n",
    "        self.criterion = nn.MSELoss()\n",
    "        self.model = args.model\n",
    "        model_name = self.model.__class__.__name__\n",
    "        model_path = os.path.join('checkpoints', model_name, 'best_model_Schrodinger.pth.tar')\n",
    "                                  \n",
    "        best_model = torch.load(model_path)\n",
    "        self.model.load_state_dict(best_model['state_dict'])        \n",
    "        self.model.to(self.device)\n",
    "        self.X, self.x, self.t = args.testset(verbose='tensor')\n",
    "        if self.device == torch.device(type='cuda'):\n",
    "            self.X = self.X.to(self.device)\n",
    "    \n",
    "    def predict(self):\n",
    "        self.model.eval()\n",
    "        u_pred, v_pred, _, _ = self.model(self.X)\n",
    "        \n",
    "        u_pred = u_pred.detach().cpu().numpy()\n",
    "        u_pred = u_pred.reshape(self.x.shape)\n",
    "        v_pred = v_pred.detach().cpu().numpy()\n",
    "        v_pred = v_pred.reshape(self.x.shape)\n",
    "        \n",
    "        h_abs_pred = np.sqrt(u_pred**2 + v_pred**2)\n",
    "        n_t = h_abs_pred.shape[0]\n",
    "        \n",
    "        # slide time index\n",
    "        n_t_1 = int(n_t*0.25 - 1)\n",
    "        n_t_2 = int(n_t*0.624 - 1)\n",
    "        n_t_3 = int(n_t*0.75 - 1)\n",
    "        \n",
    "        # Loading exact solutions:\n",
    "        data = scipy.io.loadmat('NLS.mat')\n",
    "        Exact_t = data['tt'].flatten()[:,None] # 1*256\n",
    "        Exact_x = data['x'].flatten()[:,None]  # 1*201\n",
    "        Exact = data['uu']\n",
    "        Exact_u = np.real(Exact)\n",
    "        Exact_v = np.imag(Exact)\n",
    "        Exact_h = np.sqrt(Exact_u**2 + Exact_v**2)\n",
    "        \n",
    "        # h:plot\n",
    "        fig = plt.figure(figsize=(12,3))\n",
    "        ax = fig.add_subplot(111)\n",
    "        h = ax.imshow(h_abs_pred.T, interpolation='nearest', cmap='YlGnBu',\n",
    "                      extent=[self.t.min(), self.t.max(), self.x.min(), self.x.max()], origin='lower', aspect='auto')\n",
    "        divider = make_axes_locatable(ax)\n",
    "        cax = divider.append_axes(\"right\", size=\"5%\", pad=0.05)\n",
    "        fig.colorbar(h, cax=cax)\n",
    "        \n",
    "        ic_bc_points = np.load('ic_bc_points_Schrodinger.npy')\n",
    "        ax.plot(ic_bc_points[:,1], ic_bc_points[:,0], 'kx', \n",
    "                label = 'IC and BC Data (%d points)' % (ic_bc_points.shape[0]), markersize = 4, clip_on = False)\n",
    "        ax.legend(loc='upper right',frameon=False, fontsize=12)\n",
    "    \n",
    "        line = np.linspace(self.x.min(), self.x.max(), 2)[:,None]\n",
    "        ax.plot((self.t[-1,-1]*n_t_1)/n_t*np.ones((2,1)), line, 'k--', linewidth = 2)\n",
    "        ax.plot((self.t[-1,-1]*n_t_2)/n_t*np.ones((2,1)), line, 'k--', linewidth = 2)\n",
    "        ax.plot((self.t[-1,-1]*n_t_3)/n_t*np.ones((2,1)), line, 'k--', linewidth = 2)    \n",
    "    \n",
    "        ax.set_xlabel('$t$',usetex = True,fontsize=20)\n",
    "        ax.set_ylabel('$x$',usetex = True,fontsize=20)\n",
    "        ax.set_title('$|h(t,x)|$',usetex = True,fontsize=20)\n",
    "        plt.savefig('Schrodinger_1')\n",
    "        plt.show()\n",
    "        \n",
    "        # h:slide plots\n",
    "        fig = plt.figure(figsize=(18,3))\n",
    "        ax = fig.add_subplot(131)\n",
    "        ax.plot(self.x[0,:], h_abs_pred[n_t_1,:], linewidth = 3, color='blue', label = 'Predict')       \n",
    "        ax.plot(Exact_x, Exact_h[:,n_t_1], linestyle = '--', linewidth = 3, color='red', label = 'Exact')    \n",
    "        ax.set_title('$t = %.2f$' % (self.t[n_t_1,0]),usetex = True,fontsize=20)\n",
    "        ax.set_xlabel('$x$',usetex = True,fontsize=20)\n",
    "        ax.set_ylabel('$|h(x,t)|$',usetex = True,fontsize=20)\n",
    "        ax.legend(frameon=False, loc = 'best')\n",
    "        \n",
    "        ax = fig.add_subplot(132)\n",
    "        ax.plot(self.x[0,:], h_abs_pred[n_t_2,:], linewidth = 3, color='blue', label = 'Predict')\n",
    "        ax.plot(Exact_x, Exact_h[:,n_t_2], linestyle = '--', linewidth = 3, color='red', label = 'Exact')  \n",
    "        ax.set_title('$t = %.2f$' % (self.t[n_t_2,0]),usetex = True,fontsize=20)\n",
    "        ax.set_xlabel('$x$',usetex = True,fontsize=20)\n",
    "        ax.set_ylabel('$|h(x,t)|$',usetex = True,fontsize=20)\n",
    "        ax.legend(frameon=False, loc = 'best')\n",
    "        \n",
    "        ax = fig.add_subplot(133)\n",
    "        ax.plot(self.x[0,:], h_abs_pred[n_t_3,:], linewidth = 3, color='blue', label = 'Predict')\n",
    "        ax.plot(Exact_x, Exact_h[:,n_t_3], linestyle = '--', linewidth = 3, color='red', label = 'Exact')  \n",
    "        ax.set_title('$t = %.2f$' % (self.t[n_t_3,0]),usetex = True,fontsize=20)\n",
    "        ax.set_xlabel('$x$',usetex = True,fontsize=20)\n",
    "        ax.set_ylabel('$|h(x,t)|$',usetex = True,fontsize=20)\n",
    "        ax.legend(frameon=False, loc = 'best')\n",
    "                     \n",
    "        plt.savefig('Schrodinger_2')\n",
    "        plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用Tester_Schrodinger进行预测，复现复现文章中的Figure2\n",
    "args = Options_Schrodinger().parse()\n",
    "args.problem = Problem_Schrodinger()\n",
    "\n",
    "args.model = ResPINN_Schrodinger(2, 2, dim_hidden=args.dim_hidden, res_blocks=args.res_blocks)\n",
    "args.testset = Testset_Schrodinger(args.problem, args.n_x, args.n_t, method='uniform')  \n",
    "\n",
    "tester = Tester_Schrodinger(args)\n",
    "tester.predict()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.7、对照试验\n",
    "\n",
    "使用与**2.7**相同的作图代码，得到如下的结果：\n",
    "\n",
    "#### 3.7.1、在相同的超参数的情况下，PINN和ResPINN的比较\n",
    "两者的loss曲线对比如下：\n",
    "![jupyter](Data/S_PINN_and_ResPINN/Schrodinger_train.png) \n",
    "PINN的结果如下：\n",
    "![jupyter](Data/S_PINN_and_ResPINN/pinn/Schrodinger_2.png)\n",
    "ResPINN的结果如下：\n",
    "![jupyter](Data/S_PINN_and_ResPINN/respinn/Schrodinger_2.png)\n",
    "\n",
    "#### 3.7.2、固定隐藏元个数，不同隐藏层数或残差块数对训练结果的影响：\n",
    "两者的loss曲线对比如下：\n",
    "![jupyter](Data/S_hidden_layers/Schrodinger_train.png) \n",
    "隐藏层数为4的结果如下：\n",
    "![jupyter](Data/S_hidden_layers/less/Schrodinger_2.png)\n",
    "隐藏层数为8的结果如下：\n",
    "![jupyter](Data/S_hidden_layers/more/Schrodinger_2.png)\n",
    "\n",
    "#### 3.7.3、固定隐藏层数或残差块数，不同隐藏元个数对训练结果的影响：\n",
    "两者的loss曲线对比如下：\n",
    "![jupyter](Data/S_neurons/Schrodinger_train.png) \n",
    "隐藏元个数为10的结果如下：\n",
    "![jupyter](Data/S_neurons/less/Schrodinger_2.png)\n",
    "隐藏元个数为20的结果如下：\n",
    "![jupyter](Data/S_neurons/more/Schrodinger_2.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4、Allen-Cahn方程"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "考虑带周期边界条件的Allen-Cahn方程：\n",
    "$$\n",
    "\\left\\{\n",
    "\\begin{array}{rl}\n",
    "u_t -  0.0001 u_{xx} + 5u^3 - 5 u = 0, & x \\in[-1, 1], ~~ t \\in [0, 1]\\\\\n",
    "u(0, x) = x^2\\cos(\\pi x), & \\\\\n",
    "u(t,-1) = u(t, 1), & \\\\\n",
    "u_x(t, -1) = u_x(t, 1).\n",
    "\\end{array}\n",
    "\\right.\n",
    "$$\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4.1、问题描述\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Problem_AC(object):\n",
    "    '''\n",
    "    Description of Allen-Cahn Equation\n",
    "    \n",
    "    Params\n",
    "    ====\n",
    "    x:(N,2)ndarray\n",
    "    x[:,[0]] - x , x[:,[1]]  - t\n",
    "    '''\n",
    "    \n",
    "    def __init__(self, domain = (-1, 1, 0, 1)):\n",
    "        self.domain = domain\n",
    "        \n",
    "    def __repr__(self):\n",
    "        return f'{self.__doc__}'\n",
    "    \n",
    "    def f(self, x, verbose = None):\n",
    "        out = np.zeros_like(x[:,[0]])\n",
    "        if verbose == 'tensor':\n",
    "            return torch.from_numpy(out).float().cuda()\n",
    "        return out\n",
    "\n",
    "    def ic(self, x, verbose = None):\n",
    "        '''initial condition'''\n",
    "        out = (x[:,[0]]**2) * np.cos(np.pi*x[:,[0]])\n",
    "        if verbose == 'tensor':\n",
    "            return torch.from_numpy(out).float().cuda()\n",
    "        return out"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4.2、数据集生成"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Trainset_AC(object):\n",
    "    def __init__(self, problem, *args, **kwargs):\n",
    "        self.problem = problem\n",
    "        self.domain = problem.domain\n",
    "        self.args = args\n",
    "        self.method = kwargs['method']\n",
    "        \n",
    "    def __call__(self, plot=False, verbose=None):\n",
    "        if self.method == 'uniform':\n",
    "            n_x, n_t = self.args[0], self.args[1]\n",
    "            x, x_ic, x_lb, x_ub = self._uniform_sample(n_x, n_t)\n",
    "        elif self.method == 'lhs':\n",
    "            n, n_ic, n_lb, n_ub = self.args[0], self.args[1], self.args[2], self.args[3]\n",
    "            x, x_ic, x_lb, x_ub = self._lhs_sample(n, n_ic, n_lb, n_ub)\n",
    "        f = self.problem.f(x)\n",
    "        ic = self.problem.ic(x_ic)\n",
    "        \n",
    "        if plot:\n",
    "            fig = plt.figure()\n",
    "            ax = fig.add_subplot(111)\n",
    "            ax.scatter(x[:, 0], x[:, 1], facecolor='r', s=10)\n",
    "            ax.scatter(x_ic[:, 0], x_ic[:, 1], facecolor='b', s=10)\n",
    "            ax.scatter(x_lb[:, 0], x_lb[:, 1], facecolor='g', s=10)\n",
    "            ax.scatter(x_ub[:, 0], x_ub[:, 1], facecolor='g', s=10)\n",
    "            ax.set_xlim(self.domain[0]-0.01, self.domain[1]+0.01)\n",
    "            ax.set_ylim(self.domain[2]-0.01, self.domain[3]+0.01)\n",
    "            ax.set_aspect('equal')\n",
    "            plt.show()\n",
    "            \n",
    "        if verbose is not None:\n",
    "            x = torch.from_numpy(x).float().cuda()\n",
    "            x_ic = torch.from_numpy(x_ic).float().cuda()\n",
    "            x_lb = torch.from_numpy(x_lb).float().cuda()\n",
    "            x_ub = torch.from_numpy(x_ub).float().cuda()\n",
    "            f = torch.from_numpy(f).float().cuda()\n",
    "            ic = torch.from_numpy(ic).float().cuda()\n",
    "            return x, x_ic, x_lb, x_ub, f, ic\n",
    "        return x, x_ic, x_lb, x_ub, f, ic\n",
    "        \n",
    "    def _uniform_sample(self, n_x, n_t):\n",
    "        x_min, x_max, t_min, t_max = self.domain\n",
    "        x = np.linspace(x_min, x_max, n_x)\n",
    "        t = np.linspace(t_min, t_max, n_t)\n",
    "        x, t = np.meshgrid(x, t)\n",
    "        xt = np.hstack((x.reshape(x.size, -1), t.reshape(t.size, -1)))\n",
    "        \n",
    "        mask1 =  (xt[:, 1] - t_min) == 0\n",
    "        x_ic =xt[mask1]\n",
    "        mask2 = (xt[:, 0] - x_min) == 0\n",
    "        x_lb = xt[mask2]\n",
    "        mask3 = (x_max - xt[:, 0]) == 0\n",
    "        x_ub = xt[mask3]\n",
    "        \n",
    "        x = xt[np.logical_not(mask1 + mask2 + mask3)]\n",
    "\n",
    "        return x, x_ic, x_lb, x_ub\n",
    "        \n",
    "    def _lhs_sample(self, n, n_ic, n_lb, n_ub):\n",
    "        x_min, x_max, t_min, t_max = self.domain\n",
    "\n",
    "        lb = np.array([x_min, t_min])\n",
    "        ub = np.array([x_max, t_max])\n",
    "        x = lb + (ub - lb) * lhs(2, n)\n",
    "\n",
    "        lb = np.array([x_min, t_min])\n",
    "        ub = np.array([x_max, t_min])\n",
    "        x_ic = lb + (ub - lb) * lhs(2, n_ic)\n",
    "\n",
    "        lb = np.array([x_min, t_min])\n",
    "        ub = np.array([x_min, t_max])\n",
    "        x_lb = lb + (ub - lb) * lhs(2, n_lb//2)\n",
    "\n",
    "        lb = np.array([x_max, t_min])\n",
    "        ub = np.array([x_max, t_max])\n",
    "        x_ub = lb + (ub - lb) * lhs(2, n_ub//2)\n",
    "        \n",
    "        return x, x_ic, x_lb, x_ub"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Testset_AC(object):\n",
    "    \"\"\"Dataset on a square domain\"\"\"\n",
    "    def __init__(self, problem, *args, **kwargs):\n",
    "        self.problem = problem\n",
    "        self.domain = problem.domain\n",
    "        self.args = args\n",
    "        self.method = kwargs['method']\n",
    "\n",
    "    def __repr__(self):\n",
    "        return f'{self.__doc__}'\n",
    "        \n",
    "    def __call__(self, plot=False, verbose=None):\n",
    "        if self.method == 'uniform':\n",
    "            n_x, n_t = self.args[0], self.args[1]\n",
    "            X, x, t = self._uniform_sample(n_x, n_t)\n",
    "        \n",
    "        if plot == True:\n",
    "            fig = plt.figure()\n",
    "            ax = fig.add_subplot(111)\n",
    "            ax.scatter(X[:, 0], X[:, 1], facecolor='r', s=10)\n",
    "            ax.set_xlim(self.domain[0]-0.01, self.domain[1]+0.01)\n",
    "            ax.set_ylim(self.domain[2]-0.01, self.domain[3]+0.01)\n",
    "            ax.set_aspect('equal')\n",
    "            plt.show() \n",
    "            \n",
    "        if verbose == 'tensor':\n",
    "            X = torch.from_numpy(X).float().cuda() \n",
    "        return X, x, t\n",
    "\n",
    "    def _uniform_sample(self, n_x, n_t):\n",
    "        x_min, x_max, t_min, t_max = self.domain\n",
    "        x = np.linspace(x_min, x_max, n_x)\n",
    "        t = np.linspace(t_min, t_max, n_t)\n",
    "        x, t = np.meshgrid(x, t)\n",
    "        X = np.hstack((x.reshape(x.size, -1), t.reshape(t.size, -1)))\n",
    "        return X, x, t\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4.3、网络结构\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def grad(outputs, inputs):\n",
    "    return torch.autograd.grad(outputs, inputs, grad_outputs=torch.ones_like(outputs), create_graph=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "class PINN_AC(DNN):\n",
    "    '''\n",
    "    Physics Constrained Neural Networks\n",
    "    '''\n",
    "    def __init__(self, dim_in, dim_out, dim_hidden, hidden_layers, act_name = 'tanh', init_name = 'xavier_normal'):\n",
    "        super().__init__(dim_in, dim_out, dim_hidden, hidden_layers, act_name = act_name, init_name = init_name)\n",
    "        \n",
    "    def forward(self, x, x_ic = None, x_lb=None, x_ub=None):\n",
    "        x.requires_grad_(True)\n",
    "        u = super().forward(x)\n",
    "\n",
    "        grad_u = grad(u, x)[0]\n",
    "        u_x = grad_u[:, [0]]\n",
    "        u_t = grad_u[:, [1]]\n",
    "        u_xx = grad(u_x, x)[0][:, [0]]\n",
    "\n",
    "        x.detach_()   \n",
    "\n",
    "        f = u_t - 0.0001*u_xx + 5*(u**3) - 5*u\n",
    "        \n",
    "        if x_ic is not None:\n",
    "            ic = super().forward(x_ic)\n",
    "            if x_lb is not None:\n",
    "                x_lb.requires_grad_(True)\n",
    "                lb = super().forward(x_lb)\n",
    "                lb_x = grad(lb, x_lb)[0][:, [0]]\n",
    "                x_lb.detach_()   \n",
    "                if x_ub is not None:\n",
    "                    x_ub.requires_grad_(True)\n",
    "                    ub = super().forward(x_ub)\n",
    "                    ub_x = grad(ub, x_ub)[0][:, [0]]\n",
    "                    x_ub.detach_()   \n",
    "                    return u, f, ic, lb, ub, lb_x, ub_x\n",
    "                else:\n",
    "                    return u, f, ic, lb, lb_x\n",
    "            else:\n",
    "                return u, f, ic\n",
    "        elif x_lb is not None:\n",
    "            x_lb.requires_grad_(True)\n",
    "            lb = super().forward(x_lb)\n",
    "            lb_x = grad(lb, x_lb)[0][:, [0]]\n",
    "            x_lb.detach_()  \n",
    "            if x_ub is not None:\n",
    "                x_ub.requires_grad_(True)\n",
    "                ub = super().forward(x_ub)\n",
    "                ub_x = grad(ub, x_ub)[0][:, [0]]\n",
    "                x_ub.detach_()   \n",
    "                return u, f, lb, ub, lb_x, ub_x\n",
    "            else:\n",
    "                return u, f, lb, lb_x\n",
    "        elif x_ub is not None:\n",
    "            x_ub.requires_grad_(True)\n",
    "            ub = super().forward(x_ub)\n",
    "            ub_x = grad(ub, x_ub)[0][:, [0]]\n",
    "            x_ub.detach_()   \n",
    "            return u, f, ub, ub_x\n",
    "        return u, f"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ResPINN_AC(ResDNN):\n",
    "    '''\n",
    "    Physics Constrained Neural Networks\n",
    "    '''\n",
    "    def __init__(self, dim_in, dim_out, dim_hidden, res_blocks, act_name = 'tanh', init_name = 'xavier_normal'):\n",
    "        super().__init__(dim_in, dim_out, dim_hidden, res_blocks, act_name = act_name, init_name = init_name)\n",
    "        \n",
    "    def forward(self, x, x_ic = None, x_lb=None, x_ub=None):\n",
    "        x.requires_grad_(True)\n",
    "        u = super().forward(x)\n",
    "\n",
    "        grad_u = grad(u, x)[0]\n",
    "        u_x = grad_u[:, [0]]\n",
    "        u_t = grad_u[:, [1]]\n",
    "        u_xx = grad(u_x, x)[0][:, [0]]\n",
    "\n",
    "        x.detach_()   \n",
    "\n",
    "        f = u_t - 0.0001*u_xx + 5*(u**3) - 5*u\n",
    "        \n",
    "        if x_ic is not None:\n",
    "            ic = super().forward(x_ic)\n",
    "            if x_lb is not None:\n",
    "                x_lb.requires_grad_(True)\n",
    "                lb = super().forward(x_lb)\n",
    "                lb_x = grad(lb, x_lb)[0][:, [0]]\n",
    "                x_lb.detach_()   \n",
    "                if x_ub is not None:\n",
    "                    x_ub.requires_grad_(True)\n",
    "                    ub = super().forward(x_ub)\n",
    "                    ub_x = grad(ub, x_ub)[0][:, [0]]\n",
    "                    x_ub.detach_()   \n",
    "                    return u, f, ic, lb, ub, lb_x, ub_x\n",
    "                else:\n",
    "                    return u, f, ic, lb, lb_x\n",
    "            else:\n",
    "                return u, f, ic\n",
    "        elif x_lb is not None:\n",
    "            x_lb.requires_grad_(True)\n",
    "            lb = super().forward(x_lb)\n",
    "            lb_x = grad(lb, x_lb)[0][:, [0]]\n",
    "            x_lb.detach_()  \n",
    "            if x_ub is not None:\n",
    "                x_ub.requires_grad_(True)\n",
    "                ub = super().forward(x_ub)\n",
    "                ub_x = grad(ub, x_ub)[0][:, [0]]\n",
    "                x_ub.detach_()   \n",
    "                return u, f, lb, ub, lb_x, ub_x\n",
    "            else:\n",
    "                return u, f, lb, lb_x\n",
    "        elif x_ub is not None:\n",
    "            x_ub.requires_grad_(True)\n",
    "            ub = super().forward(x_ub)\n",
    "            ub_x = grad(ub, x_ub)[0][:, [0]]\n",
    "            x_ub.detach_()   \n",
    "            return u, f, ub, ub_x\n",
    "        return u, f"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4.4、Options"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Options_AC(object):\n",
    "    def __init__(self):\n",
    "        parser = argparse.ArgumentParser()\n",
    "        parser.add_argument('--no_cuda', action='store_true', default=False, help='disable CUDA or not')\n",
    "        parser.add_argument('--dim_hidden', type=int, default=20, help='neurons in hidden layers')\n",
    "        parser.add_argument('--hidden_layers', type=int, default=6, help='number of hidden layers')\n",
    "        parser.add_argument('--res_blocks', type=int, default=4, help='number of residual blocks')\n",
    "        parser.add_argument('--dropout', type=float, default=0.5, help='dropout rate')\n",
    "        parser.add_argument('--lam1', type=float, default=1, help='weight in loss function')\n",
    "        parser.add_argument('--lam2', type=float, default=1, help='weight in loss function')\n",
    "        parser.add_argument('--lr', type=float, default=1e-3, help='initial learning rate')\n",
    "        parser.add_argument('--epochs_Adam', type=int, default=2500, help='epochs for Adam optimizer')\n",
    "        parser.add_argument('--epochs_LBFGS', type=int, default=500, help='epochs for LBFGS optimizer')\n",
    "        parser.add_argument('--step_size', type=int, default=2000, help='step size in lr_scheduler for Adam optimizer')\n",
    "        parser.add_argument('--gamma', type=float, default=0.7, help='gamma in lr_scheduler for Adam optimizer')\n",
    "        parser.add_argument('--resume', type=bool, default=False, help='resume or not')\n",
    "        parser.add_argument('--sample_method', type=str, default='uniform', help='sample method')\n",
    "        parser.add_argument('--n_x', type=int, default=512, help='sample points in x-direction for uniform sample')\n",
    "        parser.add_argument('--n_t', type=int, default=201, help='sample points in t-direction for uniform sample')\n",
    "        parser.add_argument('--n', type=int, default=20000, help='sample points in domain for lhs sample')\n",
    "        parser.add_argument('--n_ic', type=int, default=400, help='sample points at t = 0 for lhs sample')\n",
    "        parser.add_argument('--n_lb', type=int, default=400, help='sample points on the boundary for lhs sample')\n",
    "        parser.add_argument('--n_ub', type=int, default=400, help='sample points on the boundary for lhs sample')\n",
    "        parser.add_argument('--case', type=int, default=1, help='problem case')\n",
    "        self.parser = parser\n",
    "        \n",
    "        \n",
    "    def parse(self):\n",
    "        arg = self.parser.parse_args(args=[])\n",
    "        arg.cuda = not arg.no_cuda and torch.cuda.is_available()\n",
    "        arg.device = torch.device('cuda' if not arg.no_cuda and torch.cuda.is_available() else 'cpu')\n",
    "        return arg"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4.5、训练过程"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Parameters of the neural networks can be learned by minimizing the mean squared error loss\n",
    "\n",
    "$$MSE = MSE_f+MSE_0+MSE_b$$\n",
    "\n",
    "where\n",
    "\n",
    "$$MSE_f = \\frac{1}{N_f}\\sum_{i=1}^{N_f}|f(t_f^i,x_f^i)|^2,\\quad MSE_0 = \\frac{1}{N_0}\\sum_{i=1}^{N_0}|u(0,x_0^i)-u_0^i|^2$$\n",
    "\n",
    "$$MSE_b = \\frac{1}{N_b}\\sum_{i=1}^{N_b}(|u^i(t_b^i,-5)-u^i(t_b^i,5)|^2+|u_x^i(t_b^i,-5)-u_x^i(t_b^i,5)|^2)$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [],
   "source": [
    "def save_model_AC(state, is_best=None, save_dir=None):\n",
    "    last_model = os.path.join(save_dir, 'last_model_AC_Continuous.pth.tar')\n",
    "    torch.save(state, last_model)\n",
    "    if is_best:\n",
    "        best_model = os.path.join(save_dir, 'best_model_AC_Continuous.pth.tar')\n",
    "        shutil.copyfile(last_model, best_model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Trainer_AC(object):\n",
    "    def __init__(self, args):\n",
    "        self.device  = args.device\n",
    "        self.problem = args.problem\n",
    "        \n",
    "        print(f'Working device: {self.device}')\n",
    "        \n",
    "        self.lam1 = args.lam1\n",
    "        self.lam2 = args.lam2\n",
    "        self.criterion = nn.MSELoss()\n",
    "        \n",
    "        self.model = args.model\n",
    "        self.model_name = self.model.__class__.__name__\n",
    "        self.model_path = self._model_path()\n",
    "                \n",
    "        self.epochs_Adam = args.epochs_Adam\n",
    "        self.epochs_LBFGS = args.epochs_LBFGS\n",
    "        self.optimizer_Adam = optim.Adam(self.model.parameters(), lr=args.lr)\n",
    "        self.optimizer_LBFGS = optim.LBFGS(self.model.parameters(), max_iter=30, tolerance_grad=1.e-8, tolerance_change=1.e-12)\n",
    "        self.lr_scheduler = StepLR(self.optimizer_Adam, step_size=args.step_size, gamma=args.gamma)\n",
    "\n",
    "        self.model.to(self.device)\n",
    "        self.model.zero_grad()\n",
    "        \n",
    "        self.x,     self.x_ic,     self.x_lb,     self.x_ub,     self.f,     self.ic     = args.trainset(verbose='tensor')\n",
    "        self.x_val, self.x_ic_val, self.x_lb_val, self.x_ub_val, self.f_val, self.ic_val = args.validset(verbose='tensor')\n",
    "        \n",
    "        if self.device == torch.device(type='cuda'):\n",
    "            for item in [self.x,     self.x_ic,     self.x_lb,     self.x_ub,     self.f,     self.ic    ]:\n",
    "                item = item.to(self.device)\n",
    "            for item in [self.x_val, self.x_ic_val, self.x_lb_val, self.x_ub_val, self.f_val, self.ic_val]:\n",
    "                item = item.to(self.device)\n",
    "        \n",
    "        ic_bc_points = np.vstack([self.x_ic.clone().detach().cpu(), self.x_lb.clone().detach().cpu(), self.x_ub.clone().detach().cpu()])\n",
    "        np.save('ic_bc_points_AC.npy',ic_bc_points)\n",
    "        \n",
    "    def _model_path(self):\n",
    "        \"\"\"Path to save the model\"\"\"\n",
    "        if not os.path.exists('checkpoints'):\n",
    "            os.mkdir('checkpoints')\n",
    "\n",
    "        path = os.path.join('checkpoints', self.model_name)\n",
    "        if not os.path.exists(path):\n",
    "            os.mkdir(path)\n",
    "    \n",
    "        return path\n",
    "            \n",
    "    def train_Adam(self):\n",
    "        self.optimizer_Adam.zero_grad()\n",
    "\n",
    "        _, f_pred, ic_pred, lb_pred, ub_pred, lb_x_pred, ub_x_pred = self.model(self.x, self.x_ic, self.x_lb, self.x_ub)\n",
    "        \n",
    "        loss1 = self.criterion(ic_pred, self.ic)\n",
    "        loss2 = self.criterion(lb_pred, ub_pred) +  self.criterion(lb_x_pred, ub_x_pred)\n",
    "        loss3 = self.criterion(f_pred, self.f)\n",
    "        loss = loss1 + self.lam1 * loss2 + self.lam2 * loss3\n",
    "\n",
    "        loss.backward()\n",
    "        self.optimizer_Adam.step()\n",
    "        self.lr_scheduler.step()\n",
    "\n",
    "        return loss.item(), loss1.item(), loss2.item(), loss3.item()\n",
    "\n",
    "    def infos_Adam(self, epoch, loss, loss1, loss2, loss3):\n",
    "        infos = 'Adam  ' + \\\n",
    "            f'Epoch #{epoch:5d}/{self.epochs_Adam+self.epochs_LBFGS} ' + \\\n",
    "            f'Loss: {loss:.4e} = {loss1:.4e} + {self.lam1} * {loss2:.4e} + {self.lam2} * {loss3:.4e} ' + \\\n",
    "            f'lr: {self.lr_scheduler.get_lr()[0]:.2e} '\n",
    "        print(infos)\n",
    "        \n",
    "    def train_LBFGS(self):\n",
    "\n",
    "        # only used to compute loss_int and loss_bc1 for monitoring\n",
    "        _, f_pred, ic_pred, lb_pred, ub_pred, lb_x_pred, ub_x_pred = self.model(self.x, self.x_ic, self.x_lb, self.x_ub)\n",
    "\n",
    "        loss1 = self.criterion(ic_pred, self.ic)\n",
    "        loss2 = self.criterion(lb_pred, ub_pred) +  self.criterion(lb_x_pred, ub_x_pred)\n",
    "        loss3 = self.criterion(f_pred, self.f)\n",
    "        loss = loss1 + self.lam1 * loss2 + self.lam2 * loss3\n",
    "        \n",
    "        def closure():\n",
    "            if torch.is_grad_enabled():\n",
    "                self.optimizer_LBFGS.zero_grad()\n",
    "                _, f_pred, ic_pred, lb_pred, ub_pred, lb_x_pred, ub_x_pred = self.model(self.x, self.x_ic, self.x_lb, self.x_ub)\n",
    "\n",
    "                loss1 = self.criterion(ic_pred, self.ic)\n",
    "                loss2 = self.criterion(lb_pred, ub_pred) +  self.criterion(lb_x_pred, ub_x_pred)\n",
    "                loss3 = self.criterion(f_pred, self.f)\n",
    "                loss = loss1 + self.lam1 * loss2 + self.lam2 * loss3\n",
    "\n",
    "            if loss.requires_grad:\n",
    "                loss.backward()\n",
    "            return loss\n",
    "\n",
    "        self.optimizer_LBFGS.step(closure)\n",
    "        loss = closure()\n",
    "\n",
    "        return loss.item(), loss1.item(), loss2.item(), loss3.item()\n",
    "        \n",
    "    def infos_LBFGS(self, epoch, loss, loss1, loss2, loss3):\n",
    "        infos = 'LBFGS ' + \\\n",
    "            f'Epoch #{epoch:5d}/{self.epochs_Adam+self.epochs_LBFGS} ' + \\\n",
    "            f'Loss: {loss:.4e} = {loss1:.4e} + {self.lam1} * {loss2:.4e} + {self.lam2} * {loss3:.4e} '\n",
    "        print(infos)\n",
    "\n",
    "    def validate(self, epoch):\n",
    "        self.model.eval()\n",
    "        _, f_pred, ic_pred, lb_pred, ub_pred, lb_x_pred, ub_x_pred = self.model(self.x_val, self.x_ic_val, self.x_lb_val, self.x_ub_val)\n",
    "        \n",
    "        loss1 = self.criterion(ic_pred, self.ic_val)\n",
    "        loss2 = self.criterion(lb_pred, ub_pred) +  self.criterion(lb_x_pred, ub_x_pred)\n",
    "        loss3 = self.criterion(f_pred, self.f_val)\n",
    "        loss = loss1 + self.lam1 * loss2 + self.lam2 * loss3\n",
    "        \n",
    "        infos = 'Valid ' + \\\n",
    "            f'Epoch #{epoch+1:5d}/{self.epochs_Adam+self.epochs_LBFGS} ' + \\\n",
    "            f'Loss: {loss:.4e} '\n",
    "        print(infos)\n",
    "        self.model.train()\n",
    "        return loss.item()\n",
    "    \n",
    "    def train(self):\n",
    "        best_loss = 1.e10\n",
    "        train_losses_index = []\n",
    "        train_losses = []\n",
    "        valid_losses_index = []\n",
    "        valid_losses = []\n",
    "        \n",
    "        for epoch in range(self.epochs_Adam):\n",
    "            loss, loss1, loss2, loss3 = self.train_Adam()\n",
    "            train_losses_index += [epoch]\n",
    "            train_losses += [loss]\n",
    "            \n",
    "            if (epoch + 1) % 100 == 0:\n",
    "                self.infos_Adam(epoch+1, loss, loss1, loss2, loss3)\n",
    "                \n",
    "                valid_loss = self.validate(epoch)\n",
    "                is_best = valid_loss < best_loss\n",
    "                best_loss = valid_loss if is_best else best_loss                \n",
    "                state = {\n",
    "                    'epoch': epoch,\n",
    "                    'state_dict': self.model.state_dict(),\n",
    "                    'best_loss': best_loss\n",
    "                }\n",
    "                save_model_AC(state, is_best, save_dir=self.model_path)\n",
    "                valid_losses_index += [epoch]\n",
    "                valid_losses += [valid_loss]\n",
    "            \n",
    "        for epoch in range(self.epochs_Adam, self.epochs_Adam + self.epochs_LBFGS):\n",
    "            loss, loss1, loss2, loss3 = self.train_LBFGS()\n",
    "            train_losses_index += [epoch]\n",
    "            train_losses += [loss]\n",
    "            \n",
    "            if (epoch + 1) % 20 == 0:\n",
    "                self.infos_LBFGS(epoch+1, loss, loss1, loss2, loss3)\n",
    "                \n",
    "                valid_loss = self.validate(epoch)\n",
    "                is_best = valid_loss < best_loss\n",
    "                best_loss = valid_loss if is_best else best_loss                \n",
    "                state = {\n",
    "                    'epoch': epoch,\n",
    "                    'state_dict': self.model.state_dict(),\n",
    "                    'best_loss': best_loss\n",
    "                }\n",
    "                save_model_AC(state, is_best, save_dir=self.model_path)\n",
    "                valid_losses_index += [epoch]\n",
    "                valid_losses += [valid_loss]\n",
    "        \n",
    "        # loss curve\n",
    "        fig = plt.figure(figsize=(10,5))\n",
    "        ax = fig.add_subplot(111)\n",
    "        ax.set_title('Loss curve',usetex = True,fontsize=20)\n",
    "        ax.set_yscale(\"log\")\n",
    "        ax.set_xlabel('epoch',usetex = True,fontsize=20)\n",
    "        ax.set_ylabel('loss',usetex = True,fontsize=20)\n",
    "        ax.plot(train_losses_index, train_losses, color = 'g', label = 'train loss')\n",
    "        ax.plot(valid_losses_index, valid_losses, color = 'r', linestyle='--', label = 'valid loss')\n",
    "        ax.legend(frameon=False, loc = 'best')\n",
    "        plt.savefig('AC_train')\n",
    "        plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Working device: cuda\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "d:\\program files (x86)\\python\\lib\\site-packages\\torch\\optim\\lr_scheduler.py:351: UserWarning: To get the last learning rate computed by the scheduler, please use `get_last_lr()`.\n",
      "  \"please use `get_last_lr()`.\", UserWarning)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Adam  Epoch #  100/3000 Loss: 1.1061e-01 = 8.5676e-02 + 1 * 1.7472e-03 + 1 * 2.3182e-02 lr: 1.00e-03 \n",
      "Valid Epoch #  100/3000 Loss: 1.1034e-01 \n",
      "Adam  Epoch #  200/3000 Loss: 9.1662e-02 = 7.8186e-02 + 1 * 5.7242e-04 + 1 * 1.2904e-02 lr: 1.00e-03 \n",
      "Valid Epoch #  200/3000 Loss: 9.1541e-02 \n",
      "Adam  Epoch #  300/3000 Loss: 8.3073e-02 = 7.0805e-02 + 1 * 7.3068e-04 + 1 * 1.1537e-02 lr: 1.00e-03 \n",
      "Valid Epoch #  300/3000 Loss: 8.3005e-02 \n",
      "Adam  Epoch #  400/3000 Loss: 7.6221e-02 = 6.4033e-02 + 1 * 1.0200e-03 + 1 * 1.1167e-02 lr: 1.00e-03 \n",
      "Valid Epoch #  400/3000 Loss: 7.6147e-02 \n",
      "Adam  Epoch #  500/3000 Loss: 6.7474e-02 = 5.5560e-02 + 1 * 1.1599e-03 + 1 * 1.0754e-02 lr: 1.00e-03 \n",
      "Valid Epoch #  500/3000 Loss: 6.7368e-02 \n",
      "Adam  Epoch #  600/3000 Loss: 5.4194e-02 = 4.3882e-02 + 1 * 1.0510e-03 + 1 * 9.2609e-03 lr: 1.00e-03 \n",
      "Valid Epoch #  600/3000 Loss: 5.4034e-02 \n",
      "Adam  Epoch #  700/3000 Loss: 3.6709e-02 = 2.9049e-02 + 1 * 8.8288e-04 + 1 * 6.7762e-03 lr: 1.00e-03 \n",
      "Valid Epoch #  700/3000 Loss: 3.6531e-02 \n",
      "Adam  Epoch #  800/3000 Loss: 2.1644e-02 = 1.5916e-02 + 1 * 6.5511e-04 + 1 * 5.0729e-03 lr: 1.00e-03 \n",
      "Valid Epoch #  800/3000 Loss: 2.1532e-02 \n",
      "Adam  Epoch #  900/3000 Loss: 1.3784e-02 = 8.9220e-03 + 1 * 4.0884e-04 + 1 * 4.4527e-03 lr: 1.00e-03 \n",
      "Valid Epoch #  900/3000 Loss: 1.3731e-02 \n",
      "Adam  Epoch # 1000/3000 Loss: 9.9220e-03 = 5.8922e-03 + 1 * 3.1944e-04 + 1 * 3.7104e-03 lr: 1.00e-03 \n",
      "Valid Epoch # 1000/3000 Loss: 9.8938e-03 \n",
      "Adam  Epoch # 1100/3000 Loss: 7.6925e-03 = 4.4224e-03 + 1 * 3.0449e-04 + 1 * 2.9656e-03 lr: 1.00e-03 \n",
      "Valid Epoch # 1100/3000 Loss: 7.6749e-03 \n",
      "Adam  Epoch # 1200/3000 Loss: 6.2250e-03 = 3.6033e-03 + 1 * 2.7317e-04 + 1 * 2.3485e-03 lr: 1.00e-03 \n",
      "Valid Epoch # 1200/3000 Loss: 6.2128e-03 \n",
      "Adam  Epoch # 1300/3000 Loss: 5.1955e-03 = 3.0944e-03 + 1 * 2.3163e-04 + 1 * 1.8694e-03 lr: 1.00e-03 \n",
      "Valid Epoch # 1300/3000 Loss: 5.1869e-03 \n",
      "Adam  Epoch # 1400/3000 Loss: 4.4615e-03 = 2.7610e-03 + 1 * 1.9491e-04 + 1 * 1.5056e-03 lr: 1.00e-03 \n",
      "Valid Epoch # 1400/3000 Loss: 4.4553e-03 \n",
      "Adam  Epoch # 1500/3000 Loss: 3.9421e-03 = 2.5333e-03 + 1 * 1.6996e-04 + 1 * 1.2389e-03 lr: 1.00e-03 \n",
      "Valid Epoch # 1500/3000 Loss: 4.1557e-03 \n",
      "Adam  Epoch # 1600/3000 Loss: 3.5745e-03 = 2.3934e-03 + 1 * 1.4524e-04 + 1 * 1.0358e-03 lr: 1.00e-03 \n",
      "Valid Epoch # 1600/3000 Loss: 3.5714e-03 \n",
      "Adam  Epoch # 1700/3000 Loss: 3.5697e-03 = 2.2741e-03 + 1 * 1.5276e-04 + 1 * 1.1429e-03 lr: 1.00e-03 \n",
      "Valid Epoch # 1700/3000 Loss: 3.6549e-03 \n",
      "Adam  Epoch # 1800/3000 Loss: 3.1268e-03 = 2.2249e-03 + 1 * 1.1844e-04 + 1 * 7.8352e-04 lr: 1.00e-03 \n",
      "Valid Epoch # 1800/3000 Loss: 3.1252e-03 \n",
      "Adam  Epoch # 1900/3000 Loss: 3.0692e-03 = 2.1837e-03 + 1 * 1.1090e-04 + 1 * 7.7461e-04 lr: 1.00e-03 \n",
      "Valid Epoch # 1900/3000 Loss: 3.0097e-03 \n",
      "Adam  Epoch # 2000/3000 Loss: 2.8749e-03 = 2.1299e-03 + 1 * 1.0418e-04 + 1 * 6.4082e-04 lr: 4.90e-04 \n",
      "Valid Epoch # 2000/3000 Loss: 2.8739e-03 \n",
      "Adam  Epoch # 2100/3000 Loss: 2.8075e-03 = 2.1036e-03 + 1 * 1.0146e-04 + 1 * 6.0241e-04 lr: 7.00e-04 \n",
      "Valid Epoch # 2100/3000 Loss: 2.8068e-03 \n",
      "Adam  Epoch # 2200/3000 Loss: 2.7468e-03 = 2.0784e-03 + 1 * 9.9124e-05 + 1 * 5.6927e-04 lr: 7.00e-04 \n",
      "Valid Epoch # 2200/3000 Loss: 2.7462e-03 \n",
      "Adam  Epoch # 2300/3000 Loss: 2.6915e-03 = 2.0540e-03 + 1 * 9.7194e-05 + 1 * 5.4030e-04 lr: 7.00e-04 \n",
      "Valid Epoch # 2300/3000 Loss: 2.6910e-03 \n",
      "Adam  Epoch # 2400/3000 Loss: 2.6406e-03 = 2.0301e-03 + 1 * 9.5644e-05 + 1 * 5.1487e-04 lr: 7.00e-04 \n",
      "Valid Epoch # 2400/3000 Loss: 2.6401e-03 \n",
      "Adam  Epoch # 2500/3000 Loss: 2.5936e-03 = 2.0067e-03 + 1 * 9.4400e-05 + 1 * 4.9241e-04 lr: 7.00e-04 \n",
      "Valid Epoch # 2500/3000 Loss: 2.5931e-03 \n",
      "LBFGS Epoch # 2520/3000 Loss: 1.0188e-03 = 8.8535e-04 + 1 * 9.9977e-06 + 1 * 1.3959e-04 \n",
      "Valid Epoch # 2520/3000 Loss: 1.0188e-03 \n",
      "LBFGS Epoch # 2540/3000 Loss: 8.2337e-04 = 7.1608e-04 + 1 * 4.8235e-06 + 1 * 1.0707e-04 \n",
      "Valid Epoch # 2540/3000 Loss: 8.2337e-04 \n",
      "LBFGS Epoch # 2560/3000 Loss: 7.2451e-04 = 6.3976e-04 + 1 * 4.4559e-06 + 1 * 8.3458e-05 \n",
      "Valid Epoch # 2560/3000 Loss: 7.2451e-04 \n",
      "LBFGS Epoch # 2580/3000 Loss: 6.6413e-04 = 5.8233e-04 + 1 * 1.1213e-06 + 1 * 8.5007e-05 \n",
      "Valid Epoch # 2580/3000 Loss: 6.6413e-04 \n",
      "LBFGS Epoch # 2600/3000 Loss: 6.3875e-04 = 5.7049e-04 + 1 * 1.2425e-06 + 1 * 6.8129e-05 \n",
      "Valid Epoch # 2600/3000 Loss: 6.3875e-04 \n",
      "LBFGS Epoch # 2620/3000 Loss: 6.2881e-04 = 5.6731e-04 + 1 * 8.1471e-07 + 1 * 6.1341e-05 \n",
      "Valid Epoch # 2620/3000 Loss: 6.2881e-04 \n",
      "LBFGS Epoch # 2640/3000 Loss: 6.2120e-04 = 5.6057e-04 + 1 * 9.6311e-07 + 1 * 5.9733e-05 \n",
      "Valid Epoch # 2640/3000 Loss: 6.2120e-04 \n",
      "LBFGS Epoch # 2660/3000 Loss: 6.1664e-04 = 5.5467e-04 + 1 * 6.5577e-07 + 1 * 6.1511e-05 \n",
      "Valid Epoch # 2660/3000 Loss: 6.1664e-04 \n",
      "LBFGS Epoch # 2680/3000 Loss: 6.1479e-04 = 5.5158e-04 + 1 * 8.2697e-07 + 1 * 6.2387e-05 \n",
      "Valid Epoch # 2680/3000 Loss: 6.1479e-04 \n",
      "LBFGS Epoch # 2700/3000 Loss: 6.1478e-04 = 5.5160e-04 + 1 * 8.3334e-07 + 1 * 6.2350e-05 \n",
      "Valid Epoch # 2700/3000 Loss: 6.1478e-04 \n",
      "LBFGS Epoch # 2720/3000 Loss: 6.1477e-04 = 5.5160e-04 + 1 * 8.3645e-07 + 1 * 6.2338e-05 \n",
      "Valid Epoch # 2720/3000 Loss: 6.1477e-04 \n",
      "LBFGS Epoch # 2740/3000 Loss: 6.1477e-04 = 5.5160e-04 + 1 * 8.3756e-07 + 1 * 6.2329e-05 \n",
      "Valid Epoch # 2740/3000 Loss: 6.1477e-04 \n",
      "LBFGS Epoch # 2760/3000 Loss: 6.1477e-04 = 5.5160e-04 + 1 * 8.3783e-07 + 1 * 6.2328e-05 \n",
      "Valid Epoch # 2760/3000 Loss: 6.1477e-04 \n",
      "LBFGS Epoch # 2780/3000 Loss: 6.1477e-04 = 5.5160e-04 + 1 * 8.3829e-07 + 1 * 6.2332e-05 \n",
      "Valid Epoch # 2780/3000 Loss: 6.1477e-04 \n",
      "LBFGS Epoch # 2800/3000 Loss: 6.1476e-04 = 5.5159e-04 + 1 * 8.3753e-07 + 1 * 6.2339e-05 \n",
      "Valid Epoch # 2800/3000 Loss: 6.1476e-04 \n",
      "LBFGS Epoch # 2820/3000 Loss: 6.1476e-04 = 5.5159e-04 + 1 * 8.3926e-07 + 1 * 6.2335e-05 \n",
      "Valid Epoch # 2820/3000 Loss: 6.1476e-04 \n",
      "LBFGS Epoch # 2840/3000 Loss: 6.1476e-04 = 5.5158e-04 + 1 * 8.3922e-07 + 1 * 6.2336e-05 \n",
      "Valid Epoch # 2840/3000 Loss: 6.1476e-04 \n",
      "LBFGS Epoch # 2860/3000 Loss: 6.1476e-04 = 5.5157e-04 + 1 * 8.3872e-07 + 1 * 6.2347e-05 \n",
      "Valid Epoch # 2860/3000 Loss: 6.1476e-04 \n",
      "LBFGS Epoch # 2880/3000 Loss: 6.1475e-04 = 5.5157e-04 + 1 * 8.3902e-07 + 1 * 6.2344e-05 \n",
      "Valid Epoch # 2880/3000 Loss: 6.1475e-04 \n",
      "LBFGS Epoch # 2900/3000 Loss: 6.1475e-04 = 5.5157e-04 + 1 * 8.3952e-07 + 1 * 6.2346e-05 \n",
      "Valid Epoch # 2900/3000 Loss: 6.1475e-04 \n",
      "LBFGS Epoch # 2920/3000 Loss: 6.1475e-04 = 5.5156e-04 + 1 * 8.3995e-07 + 1 * 6.2352e-05 \n",
      "Valid Epoch # 2920/3000 Loss: 6.1475e-04 \n",
      "LBFGS Epoch # 2940/3000 Loss: 6.1475e-04 = 5.5156e-04 + 1 * 8.4032e-07 + 1 * 6.2352e-05 \n",
      "Valid Epoch # 2940/3000 Loss: 6.1475e-04 \n",
      "LBFGS Epoch # 2960/3000 Loss: 6.1475e-04 = 5.5155e-04 + 1 * 8.3986e-07 + 1 * 6.2360e-05 \n",
      "Valid Epoch # 2960/3000 Loss: 6.1475e-04 \n",
      "LBFGS Epoch # 2980/3000 Loss: 6.1474e-04 = 5.5154e-04 + 1 * 8.4076e-07 + 1 * 6.2361e-05 \n",
      "Valid Epoch # 2980/3000 Loss: 6.1474e-04 \n",
      "LBFGS Epoch # 3000/3000 Loss: 6.1474e-04 = 5.5153e-04 + 1 * 8.4067e-07 + 1 * 6.2374e-05 \n",
      "Valid Epoch # 3000/3000 Loss: 6.1474e-04 \n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 720x360 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 使用Trainer_AC进行训练\n",
    "args = Options_AC().parse()\n",
    "args.problem = Problem_AC()\n",
    "\n",
    "args.model = ResPINN_AC(2, 1, dim_hidden=args.dim_hidden, res_blocks=args.res_blocks)\n",
    "if args.sample_method == 'uniform':\n",
    "    args.trainset = Trainset_AC(args.problem, args.n_x, args.n_t, method='uniform')\n",
    "elif args.sample_method == 'lhs':\n",
    "    args.trainset = Trainset_AC(args.problem, args.n, args.n_ic, args.n_lb, args.n_ub, method='lhs')\n",
    "args.validset = Trainset_AC(args.problem, 200, 100, method='uniform')\n",
    "    \n",
    "trainer = Trainer_AC(args)\n",
    "trainer.train()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4.6、测试过程"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Tester_AC(object):\n",
    "    def __init__(self, args):\n",
    "        self.device  = args.device\n",
    "\n",
    "        self.criterion = nn.MSELoss()\n",
    "        self.model = args.model\n",
    "        model_name = self.model.__class__.__name__\n",
    "        model_path = os.path.join('checkpoints', model_name, 'best_model_AC_Continuous.pth.tar')\n",
    "                                  \n",
    "        best_model = torch.load(model_path)\n",
    "        self.model.load_state_dict(best_model['state_dict'])        \n",
    "        self.model.to(self.device)\n",
    "        self.X, self.x, self.t = args.testset(verbose='tensor')\n",
    "        if self.device == torch.device(type='cuda'):\n",
    "            self.X = self.X.to(self.device)\n",
    "    \n",
    "    def predict(self):\n",
    "        self.model.eval()\n",
    "        u_pred, _ = self.model(self.X)\n",
    "        \n",
    "        u_pred = u_pred.detach().cpu().numpy()\n",
    "        u_pred = u_pred.reshape(self.x.shape)\n",
    "\n",
    "        n_t = u_pred.shape[0]\n",
    "        \n",
    "        # slide time index\n",
    "        n_t_1 = int(n_t*0.10 - 1)\n",
    "        n_t_2 = int(n_t*0.40 - 1)\n",
    "        n_t_3 = int(n_t*0.70 - 1)\n",
    "        \n",
    "        # Loading exact solutions:\n",
    "        data = scipy.io.loadmat('AC.mat')\n",
    "        \n",
    "        Exact_t = data['tt'].flatten()[:,None] # 1*512\n",
    "        Exact_x = data['x'].flatten()[:,None]  # 1*201\n",
    "        Exact_u = data['uu']                   # 512*201\n",
    "\n",
    "        # h:plot\n",
    "        fig = plt.figure(figsize=(12,3))\n",
    "        ax = fig.add_subplot(111)\n",
    "        h = ax.imshow(u_pred.T, interpolation='nearest', cmap='seismic',\n",
    "                      extent=[self.t.min(), self.t.max(), self.x.min(), self.x.max()], origin='lower', aspect='auto')\n",
    "        divider = make_axes_locatable(ax)\n",
    "        cax = divider.append_axes(\"right\", size=\"5%\", pad=0.05)\n",
    "        fig.colorbar(h, cax=cax)\n",
    "        \n",
    "        ic_bc_points = np.load('ic_bc_points_AC.npy')\n",
    "        ax.plot(ic_bc_points[:,1], ic_bc_points[:,0], 'kx', \n",
    "                label = 'IC and BC Data (%d points)' % (ic_bc_points.shape[0]), markersize = 4, clip_on = False)\n",
    "        ax.legend(loc='upper right',frameon=False, fontsize=12)\n",
    "    \n",
    "        line = np.linspace(self.x.min(), self.x.max(), 2)[:,None]\n",
    "        ax.plot((self.t[-1,-1]*n_t_1)/n_t*np.ones((2,1)), line, 'w--', linewidth = 2)\n",
    "        ax.plot((self.t[-1,-1]*n_t_2)/n_t*np.ones((2,1)), line, 'w--', linewidth = 2)\n",
    "        ax.plot((self.t[-1,-1]*n_t_3)/n_t*np.ones((2,1)), line, 'w--', linewidth = 2)    \n",
    "    \n",
    "        ax.set_xlabel('$t$',usetex = True,fontsize=20)\n",
    "        ax.set_ylabel('$x$',usetex = True,fontsize=20)\n",
    "        ax.set_title('$u(t,x)$',usetex = True,fontsize=20)\n",
    "        plt.savefig('AC_1')\n",
    "        plt.show()\n",
    "        \n",
    "        # u:slide plots\n",
    "        fig = plt.figure(figsize=(15,3))\n",
    "        ax = fig.add_subplot(131)\n",
    "        ax.plot(self.x[0,:], u_pred[n_t_1,:], linewidth = 3, label = 'Predict')       \n",
    "        ax.plot(Exact_x, Exact_u[:,n_t_1], linestyle = '--', linewidth = 3, label = 'Exact')    \n",
    "        ax.set_title('$t = %.2f$' % (self.t[n_t_1,0]),usetex = True,fontsize=20)\n",
    "        ax.set_xlabel('$x$',usetex = True,fontsize=20)\n",
    "        ax.set_ylabel('$u(t,x)$',usetex = True,fontsize=20)\n",
    "        ax.legend(frameon=False, loc = 'best')\n",
    "        ax.set_xlim([self.x.min()-0.1,self.x.max()+0.1])\n",
    " \n",
    "        ax = fig.add_subplot(132)\n",
    "        ax.plot(self.x[0,:], u_pred[n_t_2,:], linewidth = 3, label = 'Predict')\n",
    "        ax.plot(Exact_x, Exact_u[:,n_t_2], linestyle = '--', linewidth = 3, label = 'Exact')  \n",
    "        ax.set_title('$t = %.2f$' % (self.t[n_t_2,0]),usetex = True,fontsize=20)\n",
    "        ax.set_xlabel('$x$',usetex = True,fontsize=20)\n",
    "        ax.set_ylabel('$u(t,x)$',usetex = True,fontsize=20)\n",
    "        ax.legend(frameon=False, loc = 'best')\n",
    "        ax.set_xlim([self.x.min()-0.1,self.x.max()+0.1])\n",
    "        \n",
    "        ax = fig.add_subplot(133)\n",
    "        ax.plot(self.x[0,:], u_pred[n_t_3,:], linewidth = 3, label = 'Predict')\n",
    "        ax.plot(Exact_x, Exact_u[:,n_t_3], linestyle = '--', linewidth = 3, label = 'Exact')  \n",
    "        ax.set_title('$t = %.2f$' % (self.t[n_t_3,0]),usetex = True,fontsize=20)\n",
    "        ax.set_xlabel('$x$',usetex = True,fontsize=20)\n",
    "        ax.set_ylabel('$u(t,x)$',usetex = True,fontsize=20)\n",
    "        ax.legend(frameon=False, loc = 'best')\n",
    "        ax.set_xlim([self.x.min()-0.1,self.x.max()+0.1])\n",
    "        \n",
    "        plt.savefig('AC_2')\n",
    "        plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 864x216 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1080x216 with 3 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 使用Tester_AC进行预测，复现复现文章中的Figure4\n",
    "args = Options_AC().parse()\n",
    "args.problem = Problem_AC()\n",
    "\n",
    "args.model = ResPINN_AC(2, 1, dim_hidden=args.dim_hidden, res_blocks=args.res_blocks)\n",
    "args.testset = Testset_AC(args.problem, 512, 201, method='uniform')  \n",
    "\n",
    "tester = Tester_AC(args)\n",
    "tester.predict()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
